Primary script 4a for Kitchel et al.Ā 2023 in prep taxonomic diversity manuscript.

library(data.table)
library(vegan)
library(sf)
library(concaveman) #polygon around points
library(betapart) #allows us to partition beta diversity
library(geosphere)
library(ggpubr) #stat_regline_equation
library(nlme)
library(mgcv) #to make gam
library(cowplot)
library(lme4)
library(stringr)

Pull dissimilarity table

#Pull Dissimilarity Means
distances_dissimilarities_allyears.r <- readRDS(here::here("output", "dissimilarities", "distances_dissimilarities_allyears.r.rds"))

#make survey and survey unit factors
distances_dissimilarities_allyears.r[,survey:=factor(survey)][,survey_unit:=factor(survey_unit)]

#adjust years
distances_dissimilarities_allyears.r[,year_adj := year-min(year)+1]

#add new variable for year in sequence per region
distances_dissimilarities_allyears.r[,first_year := min(year),.(survey_unit)]
distances_dissimilarities_allyears.r[,last_year := max(year),.(survey_unit)]

#distances_dissimilarities_allyears.r[,year_in_seq := year-first_year+1]

distances_dissimilarities_allyears.r[,years_sampled := last_year-first_year+1]

###Palette for Plotting Palette for plotting all 42 survey units

survey_unit.list <- levels(factor(distances_dissimilarities_allyears.r[,survey_unit]))

palette_42 <- c(
  "#5A5156", #AI
  "#DF00DB", #BITS-1
  "#DB8EDA", #BITS-4
  "#F6222E", #CHL
  "#F8A19F", #DFO-NF
  "#16FF32", #DFO-QCS
  "#325A9B", #EBS
  "#3283FE", #EVHOE
  "#FEAF16", #FR-CGFS
  "#fccb6d", #GMEX-Fall
  "#1C8356", #GMEX-Summer
  "#C4451C", #GOA
  "#85660D", #GRL-DE
  "#B0009F", #GSL-N
  "#BF79B8", #GSL-S
  "#1CBE4F", #ICE-GFS
  "#782AB6", #IE-IGFS
  "#90AD1C", #MEDITS
  "#6B003A", #NAM
  "#A75B00", #NEUS-Fall
  "#E3B072", #NEUS-Spring
  "#02E8B6", #NIGFS-1
  "#97E7D5", #NIGFS-4
  "#B00068", #Nor-BTS-3
  "#00B9E3", #NS-IBTS-1
  "#95E2F4", #NS-IBTS-3
  "#B3CE73", #NZ-CHAT
  "#689500", #NZ-ECSI
  "#364d02",#NZ-SUBA
  "#AAF400", #NZ-WCSI
  "#AA0DFE", #PT-IBTS
  "#7f9eb8", #ROCKALL
  "#FA0087", #S-GEORG
  "#DEA0FD", #SCS-Summer
  "#FCEF88", #SEUS-fall
  "#A59405", #SEUS-spring
  "#FCE100", #SEUS-summer
  "#544563", #SWC-IBTS-1
  "#a37fc7", #SWC-IBTS-4
  "#C075A6", #WCANN
  "#BDCDFF", #ZAF-ATL
  "#003EFF"  #ZAF-IND
)

color_link <- data.table(survey_unit = survey_unit.list,hex = palette_42)

Add names for plotting


name_helper <- data.table(Survey_Name_Season = 
                            c(
                              "Aleutian Islands",
                                    "Baltic Sea Q1",
                                    "Baltic Sea Q4",
                                    "Chile",
                                    "Newfoundland",
                                    "Queen Charlotte Sound",
                                    "Eastern Bering Sea",
                                    "Bay of Biscay",
                                    "English Channel",
                                    "Gulf of Mexico Summer",
                                    "Gulf of Alaska",
                                    "Greenland",
                                    "N Gulf of St. Lawrence",
                                    "S Gulf of St. Lawrence",
                                    "Iceland",
                                    "Irish Sea",
                                    "Mediterranean",
                                    "Namibia",
                                    "NE US Fall",
                                    "NE US Spring",
                                    "N Ireland Q1",
                                    "N Ireland Q4",
                                    "Barents Sea Norway Q3",
                                    "N Sea Q1",
                                    "N Sea Q3",
                                    "Chatham Rise NZ",
                                    "E Coast S Island NZ",
                                    "W Coast S Island NZ",
                                    "Portugal",
                                    "S Georgia",
                                  "Scotian Shelf Summer",
                                  "SE US Fall",
                                  "SE US Spring",
                                  "SE US Summer",
                                  "W Coast US",
                                  "Atlantic Ocean ZA",
                                  "Indian Ocean ZA",
                                   "Rockall Plateau",
                                  "Scotland Shelf Sea Q1",
                                  "Scotland Shelf Sea Q4",
                                  "Falkland Islands",
                                  "Gulf of Mexico Fall",
                                  "Barents Sea Norway Q1",
                                  "Sub-Antarctic NZ",
                                  "Scotian Shelf Spring"),
                          survey_unit = c(
                                  "AI",        
                                  "BITS-1",    
                                  "BITS-4",    
                                  "CHL",       
                                  "DFO-NF",    
                                  "DFO-QCS",   
                                  "EBS",       
                                  "EVHOE",     
                                  "FR-CGFS",   
                                  "GMEX-Summer",
                                  "GOA",       
                                  "GRL-DE",    
                                  "GSL-N",     
                                  "GSL-S",     
                                  "ICE-GFS",   
                                  "IE-IGFS",   
                                  "MEDITS",    
                                  "NAM",       
                                  "NEUS-Fall", 
                                  "NEUS-Spring",
                                  "NIGFS-1",   
                                  "NIGFS-4",   
                                  "Nor-BTS-3", 
                                  "NS-IBTS-1", 
                                  "NS-IBTS-3", 
                                  "NZ-CHAT",   
                                  "NZ-ECSI",   
                                  "NZ-WCSI",   
                                  "PT-IBTS",   
                                  "S-GEORG",   
                                  "SCS-SUMMER",
                                  "SEUS-fall", 
                                  "SEUS-spring",
                                  "SEUS-summer",
                                  "WCANN",     
                                  "ZAF-ATL",   
                                  "ZAF-IND",
                                  "ROCKALL",
                                  "SWC-IBTS-1",
                                  "SWC-IBTS-4",
                                  "FALK",
                                  "GMEX-Fall",
                                  "Nor-BTS-1",
                                  "NZ-SUBA",
                                  "SCS-SPRING"
                          ))


color_link <- name_helper[color_link, on = "survey_unit"]

#save to pull into other scripts
fwrite(color_link, here::here("output","color_link.csv"))

##Make GAMs

Bray Curtis

bray_curtis_total_gam <- gam(bray_curtis_dissimilarity_total_mean ~ year + s(survey_unit, year, bs = "fs", m = 1),#random smooth
                            data = distances_dissimilarities_allyears.r)

Jaccard

jaccard_total_gam <- gam(jaccard_dissimilarity_total_mean ~ year + s(survey_unit, year, bs = "fs", m = 1),#random smooth
                            data = distances_dissimilarities_allyears.r)

##Make LMERS

Bray These all converged

#running with lme instead of lmer gave same results, but allowed for calculation of p-value
bray_curtis_total_lme <- lme(bray_curtis_dissimilarity_total_mean ~ year_adj, random = (~1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)

#but also run with lmer for confint
#total
bray_curtis_total_lmer <- lmer(bray_curtis_dissimilarity_total_mean ~ year_adj + (1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)

#balanced (for comparison plot)
bray_curtis_balanced_lmer <- lmer(bray_curtis_dissimilarity_balanced_mean ~ year_adj + (1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)
Warning: Model failed to converge with max|grad| = 0.0930452 (tol = 0.002, component 1)
#gradient (for comparison plot)
bray_curtis_gradient_lmer <- lmer(bray_curtis_dissimilarity_gradient_mean ~ year_adj + (1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)
Warning: Model failed to converge with max|grad| = 0.5086 (tol = 0.002, component 1)
#Jaccard total (for comparison plot)
jaccard_total_lmer <- lmer(jaccard_dissimilarity_total_mean ~ year_adj + (1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)
Warning: Model failed to converge with max|grad| = 0.163399 (tol = 0.002, component 1)
summary(bray_curtis_total_lme)
Linear mixed-effects model fit by REML
  Data: distances_dissimilarities_allyears.r 

Random effects:
 Formula: ~1 + year_adj | survey_unit
 Structure: General positive-definite, Log-Cholesky parametrization
            StdDev      Corr  
(Intercept) 0.106024695 (Intr)
year_adj    0.001955226 -0.769
Residual    0.024352895       

Fixed effects:  bray_curtis_dissimilarity_total_mean ~ year_adj 
 Correlation: 
         (Intr)
year_adj -0.798

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-4.93606507 -0.46317561  0.02981855  0.50587465  4.55375745 

Number of Observations: 896
Number of Groups: 42 
anova(bray_curtis_total_lme)

bray_curtis_total_coefs <- data.table(coef(bray_curtis_total_lme))
bray_curtis_total_coefs[,survey_unit := rownames(coef(bray_curtis_total_lme))][,Year := round(year_adj,5)][,Intercept := round(`(Intercept)`,2)]
#View(bray_curtis_total_coefs)

bray_curtis_total_coefs <- bray_curtis_total_coefs[color_link, on = "survey_unit"]

bray_curtis_total_coefs.exp <- bray_curtis_total_coefs[,.(Survey_Name_Season, Intercept, Year)]

#export this table
fwrite(bray_curtis_total_coefs.exp, file = here::here("output","bray_curtis_total_coefs.exp.csv"))

Also, build a simple linear model with an interaction (instead of random slope and intercept for survey) THIS IS HOW WE CLASSIFY SURVEYS

bray_curtis_total_lm <- lm(bray_curtis_dissimilarity_total_mean ~ year_adj*survey_unit,data = distances_dissimilarities_allyears.r)

bray_curtis_total_coefs <- data.table(summary(bray_curtis_total_lm)$coefficients)
  bray_curtis_total_coefs[,var := rownames(summary(bray_curtis_total_lm)$coefficients)]
  
  #limit to interactions only (check this if there are any model changes!) row 2 and rows 44:84
  bray_curtis_total_coefs.r <- bray_curtis_total_coefs[c(2,44:84),]
  
  #adjust survey unit name by deleting beginning of string
  bray_curtis_total_coefs.r[,survey_unit := substr(var, 21, str_length(var))][var == "year_adj",survey_unit := "AI"]
  
  #calculate interaction coefficients
  AI_estimate <- bray_curtis_total_coefs.r[1,Estimate]
  bray_curtis_total_coefs.r[1,survey_unit_coefficient := AI_estimate]
  bray_curtis_total_coefs.r[2:42,survey_unit_coefficient := (AI_estimate + Estimate)]
  
  #homogenizing vs differentiating
  bray_curtis_total_coefs.r[,differentiating := ifelse((`Std. Error`< abs(survey_unit_coefficient) & survey_unit_coefficient > 0),1,0)][,homogenizing := ifelse((`Std. Error`< abs(survey_unit_coefficient) & survey_unit_coefficient < 0),1,0)]
  
  #lower and upper CI
    bray_curtis_total_coefs.r[,lwr := survey_unit_coefficient-`Std. Error`][,upr:= survey_unit_coefficient+`Std. Error`]
  
  bray_curtis_total_coefs_sum <- data.table(differentiating = sum(  bray_curtis_total_coefs.r$differentiating), homogenizing = sum(  bray_curtis_total_coefs.r$homogenizing))
  
  #hex by trend
  bray_curtis_total_coefs.r[,trend_color := ifelse(homogenizing == 1, "#e7ac5b", ifelse(differentiating == 1,"#91c874","#cbbfde"))]
  
  bray_curtis_total_coefs.r_alpha <- setorder(bray_curtis_total_coefs.r, Survey_Name_Season)
Error in setorderv(x, cols, order, na.last) : 
  some columns are not in the data.table: Survey_Name_Season

Get LMER model as predictions


# need to sort out year in seq versus overall year models
#new data for lmer
lmer_year <- seq(min(distances_dissimilarities_allyears.r[,year]), max(distances_dissimilarities_allyears.r[,year]), by = 0.1)

lmer_year_adj <- seq(min(distances_dissimilarities_allyears.r[,year_adj]), max(distances_dissimilarities_allyears.r[,year_adj]), by = 0.1)

#predict average lmer
lmer_bray_total_predictions <- data.table(year = lmer_year, year_adj = lmer_year_adj)

#confidence intervals
bray_curtis_total_lmer_confint <- confint(bray_curtis_total_lmer)
Computing profile confidence intervals ...
#populate data table of lmer predictions
lmer_bray_total_predictions[,bray_curtis_lmer_preds := fixef(bray_curtis_total_lmer)[[1]] + fixef(bray_curtis_total_lmer)[[2]] * year_adj][,bray_curtis_lmer_preds_lowerCI := bray_curtis_total_lmer_confint[5] + bray_curtis_total_lmer_confint[6] * year_adj][,bray_curtis_lmer_preds_upperCI := bray_curtis_total_lmer_confint[11] + bray_curtis_total_lmer_confint[12] * year_adj]

# need to sort out year in seq versus overall year models
#new data for lmer


#predict average lmer
lmer_bray_balanced_predictions <- data.table(year = lmer_year, year_adj = lmer_year_adj)

#confidence intervals
bray_curtis_balanced_lmer_confint <- confint(bray_curtis_balanced_lmer)
Computing profile confidence intervals ...
#populate data table of lmer predictions
lmer_bray_balanced_predictions[,bray_curtis_lmer_preds := fixef(bray_curtis_balanced_lmer)[[1]] + fixef(bray_curtis_balanced_lmer)[[2]] * year_adj][,bray_curtis_lmer_preds_lowerCI := bray_curtis_balanced_lmer_confint[5] + bray_curtis_balanced_lmer_confint[6] * year_adj][,bray_curtis_lmer_preds_upperCI := bray_curtis_balanced_lmer_confint[11] + bray_curtis_balanced_lmer_confint[12] * year_adj]

# need to sort out year in seq versus overall year models


#predict average lmer
lmer_bray_gradient_predictions <- data.table(year = lmer_year, year_adj = lmer_year_adj)

#confidence intervals
bray_curtis_gradient_lmer_confint <- confint(bray_curtis_gradient_lmer)
Computing profile confidence intervals ...
#populate data table of lmer predictions
lmer_bray_gradient_predictions[,bray_curtis_lmer_preds := fixef(bray_curtis_gradient_lmer)[[1]] + fixef(bray_curtis_gradient_lmer)[[2]] * year_adj][,bray_curtis_lmer_preds_lowerCI := bray_curtis_gradient_lmer_confint[5] + bray_curtis_gradient_lmer_confint[6] * year_adj][,bray_curtis_lmer_preds_upperCI := bray_curtis_gradient_lmer_confint[11] + bray_curtis_gradient_lmer_confint[12] * year_adj]

# need to sort out year in seq versus overall year models


#predict average lmer
lmer_jaccard_total_predictions <- data.table(year = lmer_year, year_adj = lmer_year_adj)

#confidence intervals
jaccard_total_lmer_confint <- confint(jaccard_total_lmer)
Computing profile confidence intervals ...
#populate data table of lmer predictions
lmer_jaccard_total_predictions[,jaccard_lmer_preds := fixef(jaccard_total_lmer)[[1]] + fixef(jaccard_total_lmer)[[2]] * year_adj][,jaccard_lmer_preds_lowerCI := jaccard_total_lmer_confint[5] + jaccard_total_lmer_confint[6] * year_adj][,jaccard_lmer_preds_upperCI := jaccard_total_lmer_confint[11] + jaccard_total_lmer_confint[12] * year_adj]

###Move forward with Bray Curtis total (others to supplement, although will include in plot below) Coefficients for LMER by survey_unit

#unique survey unit year combos
survey_unit_sampling_years <- unique(distances_dissimilarities_allyears.r[,.(survey_unit, year_adj, year, years_sampled)])

#just # years
survey_unit_years <- unique(survey_unit_sampling_years[,.(survey_unit, years_sampled)])

# see group coefficients
model_coefs_reduced <- data.table(transform(as.data.frame(ranef(bray_curtis_total_lmer)), lwr = condval - 1.96*condsd, upr = condval + 1.96*condsd))
#https://stackoverflow.com/questions/69805532/extract-the-confidence-intervals-of-lmer-random-effects-plotted-with-dotplotra


#ONLY SLOPES
model_coefs_reduced <- model_coefs_reduced[term == "year_adj",]

model_coefs_reduced[,survey_unit := grp][,year_adj := condval]

#merge with duration of survey
model_coefs_reduced_length <- model_coefs_reduced[survey_unit_sampling_years, on = "survey_unit"]


model_coefs_reduced_length[,years_sampled := as.numeric(years_sampled)][,Directional_Change := ifelse(year_adj > 0, "Differentiation","Homogenization")]

#does it cross zero?
model_coefs_reduced_length[,significant := ifelse(lwr >0 & upr>0,T,ifelse(lwr<0 & upr<0,T,F))]

#significant directional change
model_coefs_reduced_length[,Directional_Change_sig := ifelse(year_adj > 0 & significant == T, "Differentiation",ifelse(year_adj < 0 & significant == T, "Homogenization", "No trend in\ndissimilarity"))]


#min max distances_dissimilarities
min_bray_reduced <- min(distances_dissimilarities_allyears.r[,bray_curtis_dissimilarity_total_mean], na.rm = T)
max_bray_reduced <- max(distances_dissimilarities_allyears.r[,bray_curtis_dissimilarity_total_mean], na.rm = T)

model_coefs_reduced_length <- model_coefs_reduced_length[color_link, on = "survey_unit"]

#delete any NAs
model_coefs_reduced_length <- na.omit(model_coefs_reduced_length, cols = "significant")

#order table by coefficient
setorder(model_coefs_reduced_length, year_adj)

BC_total_model_coefs_reduced_length.unique <- unique(model_coefs_reduced_length[,.(condval,condsd, lwr, upr, survey_unit, year_adj, years_sampled, Directional_Change, hex, Survey_Name_Season, significant, Directional_Change_sig)]) 

#extract color hexes
#year adj coef order
color_year_adj_order <- BC_total_model_coefs_reduced_length.unique[,hex]

#alphabetical order
BC_total_model_coefs_reduced_length.unique.alpha <- setorder(BC_total_model_coefs_reduced_length.unique, Survey_Name_Season)

BC_total_model_coefs_reduced_length.unique.alpha[,trend_color := ifelse(Directional_Change_sig == "Homogenization", "#e7ac5b", ifelse(Directional_Change_sig == "Differentiation","#91c874","#cbbfde"))]

color_alpha_order <- BC_total_model_coefs_reduced_length.unique.alpha[,hex]
color_alpha_order_bytrend <- BC_total_model_coefs_reduced_length.unique.alpha[, trend_color]

saveRDS(BC_total_model_coefs_reduced_length.unique, here::here("output","region_stats","BC_total_model_coefs_reduced_length.unique.Rds"))

Coefficients by interactions of linear model

#extract color hexes
#year adj coef order
color_year_adj_order <- BC_total_model_coefs_reduced_length.unique[,hex]

#alphabetical order
BC_total_model_coefs_reduced_length.unique.alpha <- setorder(BC_total_model_coefs_reduced_length.unique, Survey_Name_Season)

BC_total_model_coefs_reduced_length.unique.alpha[,trend_color := ifelse(Directional_Change_sig == "Homogenization", "#e7ac5b", ifelse(Directional_Change_sig == "Differentiation","#91c874","#cbbfde"))]

color_alpha_order <- BC_total_model_coefs_reduced_length.unique.alpha[,hex]
color_alpha_order_bytrend <- BC_total_model_coefs_reduced_length.unique.alpha[, trend_color]

#key trend color and survey
trend_color_survey <- unique(BC_total_model_coefs_reduced_length.unique.alpha[,.(survey_unit, Survey_Name_Season,hex, trend_color)])

saveRDS(BC_total_model_coefs_reduced_length.unique, here::here("output","region_stats","BC_total_model_coefs_reduced_length.unique.Rds"))

Total versus balanced BC plot

ggplot(distances_dissimilarities_allyears.r) +
  geom_point(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_balanced_mean)) +
  geom_abline(slope = 1, intercpet = 0) +
  geom_smooth(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_balanced_mean)) +
  theme_classic() +
  labs(x = "Total BC dissimilarity",  y = "Balanced changes in abundance/biomass")
Warning: Ignoring unknown parameters: `intercpet`

ggplot(distances_dissimilarities_allyears.r) +
  geom_point(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_gradient_mean)) +
  geom_abline(slope = 1, intercpet = 0) +
  geom_smooth(aes(bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_gradient_mean)) +
  theme_classic() +
  labs(x = "Total BC dissimilarity",  y = "Abundance/biomass gradient")
Warning: Ignoring unknown parameters: `intercpet`
#all on one plot
#reduced
distances_dissimilarities_allyears.r.r <- distances_dissimilarities_allyears.r[,.(year, bray_curtis_dissimilarity_total_mean, bray_curtis_dissimilarity_gradient_mean, bray_curtis_dissimilarity_balanced_mean, jaccard_dissimilarity_total_mean)]

#wide to long
dissim_long <- melt(distances_dissimilarities_allyears.r.r, id.vars = c("year"), variable.name = "Dissimilarity metric")

dissim_long[,`Dissimilarity metric` := factor(`Dissimilarity metric`, levels = c( "bray_curtis_dissimilarity_total_mean","bray_curtis_dissimilarity_balanced_mean","bray_curtis_dissimilarity_gradient_mean", "jaccard_dissimilarity_total_mean"))]

BC_dissimilarity_components <- ggplot() +
  geom_point(data = dissim_long[`Dissimilarity metric` != "jaccard_dissimilarity_total_mean",], aes(x = year, y = value, color = `Dissimilarity metric`), alpha = 0.2, size = 1) +
  geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "black", alpha = 0.3) +
  geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
  #balanced
    geom_ribbon(data = lmer_bray_gradient_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "cadetblue3", alpha = 0.3) +
  geom_line(data = lmer_bray_gradient_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "cadetblue3") +
  #gradient
    geom_ribbon(data = lmer_bray_balanced_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "darksalmon", alpha = 0.3) +
  geom_line(data = lmer_bray_balanced_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "darksalmon") +
  #fix. colors of points
  scale_color_manual(values = c("black","darksalmon","cadetblue3"), labels = c("Total","Balanced variation\nin abundance","Biomass gradient")) +
  labs(x = "Year", y = "Value") +
  lims(y = c(min(dissim_long$value), max(dissim_long$value))) +
  theme_classic() +
  theme(legend.position = c(0.17,0.37))

ggsave(BC_dissimilarity_components, path = here::here("figures"), filename=("BC_dissimilarity_components.jpg"), width = 6.5, height = 5, units = "in")

#Jaccard
Jaccard_dissimilarity <- ggplot() +
  geom_point(data = dissim_long[`Dissimilarity metric` == "jaccard_dissimilarity_total_mean"], aes(x = year, y = value), alpha = 0.2, size = 1) +
  geom_ribbon(data = lmer_jaccard_total_predictions, aes(x = year, ymin = jaccard_lmer_preds_lowerCI, ymax = jaccard_lmer_preds_upperCI), fill = "black", alpha = 0.3) +
  geom_line(data = lmer_jaccard_total_predictions, aes(x = year, y = jaccard_lmer_preds), color = "black") +
  labs(x = "Year", y = "Total Jaccard dissimilarity") +
  lims(y = c(min(dissim_long$value), max(dissim_long$value))) +
  theme_classic()

ggsave(Jaccard_dissimilarity, path = here::here("figures"), filename=("Jaccard_dissimilarity.jpg"), width = 6.5, height = 5, units = "in")

#merge
library(cowplot)
all_dissimilarities_over_time <- plot_grid(BC_dissimilarity_components + theme(legend.background = element_rect(fill = "transparent")),
                                           Jaccard_dissimilarity,
                                           ncol = 2, align = "hv", labels = c("a.","b."))

ggsave(all_dissimilarities_over_time, filename = "all_dissimilarities_over_time.jpg", path = here::here("figures"), width = 10, height = 4.5, units = "in")

NA
NA

Lollipop SE plot by linear trend experienced

#"#73BA4D","#E0962C","#cbbfde"

BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend <- ggplot() +
    geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, color = Directional_Change_sig), stat = 'identity') +
  scale_color_manual(values = c("#73BA4D","#E0962C","#cbbfde"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length\n(years)") +
  geom_hline(yintercept = 0) +
  scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.3,0.8), legend.direction = "vertical", legend.text = element_text(size = 15), legend.title = element_text(size = 16))
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: label
directional_change_legend_plot_colorbytrend <- BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend + 
  theme(legend.position = "right", legend.background = element_rect(fill= "transparent"), 
         legend.text = element_text(size = 15), legend.title = element_text(size = 16)) +
  guides(colour = guide_legend(override.aes = list(size=6)), size = "none")

###############
#FOR LINEAR MODEL INSTEAD OF LINEAR MIXED EFFECTS
###############
bray_curtis_total_coefs.r <- bray_curtis_total_coefs.r[color_link, on = "survey_unit"]
bray_curtis_total_coefs.r <- survey_unit_years[bray_curtis_total_coefs.r, on="survey_unit"]

bray_curtis_total_coefs.r[,Directional_Change_sig := ifelse(differentiating > 0, "Differentiation",ifelse(homogenizing > 0 , "Homogenization", "No trend in\ndissimilarity"))]

(BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend_LINEAR_MODEL <- ggplot() +
    geom_errorbar(data = bray_curtis_total_coefs.r, aes(x = reorder(Survey_Name_Season, survey_unit_coefficient) , y = survey_unit_coefficient, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = bray_curtis_total_coefs.r, aes(x = reorder(Survey_Name_Season, survey_unit_coefficient) , y = survey_unit_coefficient, label = Survey_Name_Season, size = years_sampled, color = Directional_Change_sig), stat = 'identity') +
  scale_color_manual(values = c("#73BA4D","#E0962C","#cbbfde"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length\n(years)") +
  geom_hline(yintercept = 0) +
  #scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.3,0.8), legend.direction = "vertical", legend.text = element_text(size = 15), legend.title = element_text(size = 16)))
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: label
ggsave(BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend_LINEAR_MODEL, 
       path = here::here("figures"), filename = "BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend_LINEAR_MODEL.jpg", height = 7, width = 7)


#Still need to edit
directional_change_legend_plot_colorbytrend <- BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend + 
  theme(legend.position = "right", legend.background = element_rect(fill= "transparent"), 
         legend.text = element_text(size = 15), legend.title = element_text(size = 16)) +
  guides(colour = guide_legend(override.aes = list(size=6)), size = "none")

Wavy Line Plot for GAMs

Generate predicted values (this datatable will hold both jaccard and bray curtis)


#add colors and names to full dissimilarity data table
distances_dissimilarities_allyears.r <- distances_dissimilarities_allyears.r[color_link, on = "survey_unit"]

#generate new data to smooth lines (need year and season survey combinations)
year_survey_unit_expand.dt <- data.table(survey_unit = as.character(NULL), year = as.numeric(NULL), year_adj = as.numeric(NULL ))

for (i in 1:length(survey_unit.list)) {
  #generate year vectors
  survey_unit_years <- unique(distances_dissimilarities_allyears.r[survey_unit == survey_unit.list[i],.(survey_unit, year, year_adj)])
  
  years <- seq(min(survey_unit_years[,year]), max(survey_unit_years[,year]), by = 0.1)
  
  year_adjust <- seq(min(survey_unit_years[,year_adj]), max(survey_unit_years[,year_adj]), by = 0.1)
  
  year_survey_unit_expand.dt_addition <- data.table(survey_unit = survey_unit.list[i], year = years, year_adj = year_adjust)
  
  year_survey_unit_expand.dt <- rbind(year_survey_unit_expand.dt, year_survey_unit_expand.dt_addition)
}

#add colors and names to full year and survey unit combination table
year_survey_unit_expand.dt <- year_survey_unit_expand.dt[color_link, on = "survey_unit"]

Get model as predictions Bray Curtis

#for plotting, get model as predictions
bray_curtis_total_gam_predictions <- predict(bray_curtis_total_gam, se.fit = TRUE, newdata = year_survey_unit_expand.dt)

#merge into table
year_survey_unit_expand.dt[,bray_glm_mod_fit := bray_curtis_total_gam_predictions$fit][,bray_glm_mod_fit_SE := bray_curtis_total_gam_predictions$se.fit]

Jaccard Get model as predictions

#for plotting, get model as predictions
jaccard_total_gam_predictions <- predict(jaccard_total_gam, se.fit = TRUE, newdata = year_survey_unit_expand.dt)

#merge into table
year_survey_unit_expand.dt[,jaccard_glm_mod_fit := jaccard_total_gam_predictions$fit][,jaccard_glm_mod_fit_SE := jaccard_total_gam_predictions$se.fit]

Produce Plot of GAM and mean LMER line

points_wavylines_bray_total_year_reduced_gam_nolmer <- ggplot() +
 # geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.2) +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r,cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 color = Survey_Name_Season), alpha = 0.5, size = 1) +
    geom_line(data = na.omit(year_survey_unit_expand.dt,cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt,cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
 # geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =  color_alpha_order, name = "Survey Unit") +
  scale_fill_manual(values =  color_alpha_order, guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
       y = c(0.15,0.9)) +
  xlab("Year") +
ylab("total BC dissimilarity") +
  theme(legend.position = "null")

points_wavylines_bray_total_year_reduced_gam_nolmer

ggsave(points_wavylines_bray_total_year_reduced_gam_nolmer, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_nolmer.jpg", height = 5, width = 5, unit = "in")


#with lmer

points_wavylines_bray_total_year_reduced_gam <- ggplot() +
  geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r, cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season), alpha = 0.6) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
  geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =  color_alpha_order, name = "Survey Unit") +
  scale_fill_manual(values =  color_alpha_order, guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year]))) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam

ggsave(points_wavylines_bray_total_year_reduced_gam, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam.jpg", height = 6, width = 6, unit = "in")


#ALT
#plot all, but same color scheme (grey)
points_wavylines_bray_total_year_reduced_gam_greyscale <- ggplot() +
  geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
  geom_point(data = distances_dissimilarities_allyears.r,
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
    geom_line(data = year_survey_unit_expand.dt,
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season), alpha = 0.6) +
  geom_ribbon(data = year_survey_unit_expand.dt, aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
  geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =  rep("black", times = length(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))), name = "Survey Unit") +
  scale_fill_manual(values =  rep("black", times = length(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))), guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year]))
       ) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_greyscale

ggsave(points_wavylines_bray_total_year_reduced_gam_greyscale, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_greyscale.jpg", height = 6, width = 6, unit = "in")

Alternative, color by trend


points_wavylines_bray_total_year_reduced_gam_colorbytrend <- ggplot() +
  geom_ribbon(data = lmer_bray_total_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r, cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season), alpha = 0.6) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
  geom_line(data = lmer_bray_total_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
    scale_color_manual(values =    linear_model_color_order_factorlevels$trend_color, name = "Survey Unit") +
  scale_fill_manual(values =    linear_model_color_order_factorlevels$trend_color, guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),y = c(0.49,0.95)) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_colorbytrend

ggsave(points_wavylines_bray_total_year_reduced_gam_colorbytrend, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_colorbytrend.jpg", height = 6, width = 11, unit = "in")



points_wavylines_bray_total_year_reduced_gam_colorbytrend_squigglesonly <- ggplot() +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r, cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season), alpha = 0.6) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
    scale_color_manual(values =    linear_model_color_order_factorlevels$trend_color, name = "Survey Unit") +
  scale_fill_manual(values =    linear_model_color_order_factorlevels$trend_color, guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])), y = c(0.49,0.95)) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_colorbytrend_squigglesonly

ggsave(points_wavylines_bray_total_year_reduced_gam_colorbytrend_squigglesonly, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_colorbytrend_squigglesonly.jpg", height = 6, width = 11, unit = "in")

BC

#plot each independently for supplement
#all survey names = 
all_survey_names <- sort(unique(color_link$Survey_Name_Season))
#list of plots
points_wavylines_bray_total_year_reduced_gam_individual <- list()
for (i in 1:length(all_survey_names)) {
points_wavylines_bray_total_year_reduced_gam_individual[[i]] <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i]],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean), alpha = 0.4, color = "black") +
    geom_line(data = year_survey_unit_expand.dt[Survey_Name_Season == all_survey_names[i]],
             aes(x = year,
                 y = bray_glm_mod_fit), alpha = 0.6) +
  geom_ribbon(data = year_survey_unit_expand.dt[Survey_Name_Season == all_survey_names[i]], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.1) + #add standard error
  theme_classic() +
#  lims(x = c(min(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i],year]),max(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i],year])),
#       y = c(0.15,0.9)) +
  xlab("Year") +
ylab("beta-diversity") +
  facet_wrap(~Survey_Name_Season, ncol = 5) +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

print(points_wavylines_bray_total_year_reduced_gam_individual[[i]])

}

saveRDS(points_wavylines_bray_total_year_reduced_gam_individual, here::here("figures","points_wavylines_bray_total_year_reduced_gam_individual.Rds"))

#print to pdf
library(gridExtra)

ggsave(
   filename = here::here("figures","points_wavylines_bray_total_year_reduced_gam_individual.pdf"), 
   plot = marrangeGrob(points_wavylines_bray_total_year_reduced_gam_individual, nrow=1, ncol=1), 
   width = 8.5, height = 11
)

#Alternatively, split into 2 and use facet
#first 24
points_wavylines_bray_total_year_reduced_gam_individual_facet_1_24 <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r[Survey_Name_Season  %in% all_survey_names[c(1:24)]],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean), alpha = 0.7) +
    geom_line(data = year_survey_unit_expand.dt[Survey_Name_Season   %in% all_survey_names[c(1:24)]],
             aes(x = year,
                 y = bray_glm_mod_fit)) +
  geom_ribbon(data = year_survey_unit_expand.dt[Survey_Name_Season  %in% all_survey_names[c(1:24)]],
aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.5) + #add standard error
    geom_smooth(data = distances_dissimilarities_allyears.r[Survey_Name_Season  %in% all_survey_names[c(1:24)]],
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 color = Survey_Name_Season,
                 fill = Survey_Name_Season), alpha = 0.4, method = "lm", linewidth = 0.5) +
    scale_color_manual(values =    linear_model_color_order_factorlevels$trend_color[1:24], name = "Survey Unit") +
    scale_fill_manual(values =    linear_model_color_order_factorlevels$trend_color[1:24], name = "Survey Unit") +
  theme_classic() +
  xlab("Year") +
ylab("β-diversity") +
  facet_wrap(~Survey_Name_Season, ncol = 4, scales = "free") +
  theme(axis.text = element_text(size = 8), axis.title = element_text(size = 12), legend.position = "null")

ggsave(points_wavylines_bray_total_year_reduced_gam_individual_facet_1_24, path =  here::here("figures"), filename = "points_wavylines_bray_total_year_reduced_gam_individual_facet_1_24.png", height = 11, width = 9)

#second half
distances_dissimilarities_allyears.r_second <- distances_dissimilarities_allyears.r[Survey_Name_Season  %in% all_survey_names[c(25:42)]]
distances_dissimilarities_allyears.r_second <- setorder(distances_dissimilarities_allyears.r_second,Survey_Name_Season)
year_survey_unit_expand.dt_second <- year_survey_unit_expand.dt[Survey_Name_Season   %in% all_survey_names[c(25:42)]]
year_survey_unit_expand.dt_second <- setorder(year_survey_unit_expand.dt_second, Survey_Name_Season)

points_wavylines_bray_total_year_reduced_gam_individual_facet_25_42 <- ggplot() +
  geom_point(data = distances_dissimilarities_allyears.r_second,
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean), alpha = 0.7) +
    geom_line(data = year_survey_unit_expand.dt_second,
             aes(x = year,
                 y = bray_glm_mod_fit)) +
  geom_ribbon(data = year_survey_unit_expand.dt_second,
aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.5) + #add standard error
  geom_smooth(data = distances_dissimilarities_allyears.r_second,
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 color = Survey_Name_Season,
                 fill = Survey_Name_Season), alpha = 0.4, method = "lm", linewidth = 0.5) +
    scale_color_manual(values =    linear_model_color_order_factorlevels$trend_color[25:42], name = "Survey Unit") +
    scale_fill_manual(values =    linear_model_color_order_factorlevels$trend_color[25:42], name = "Survey Unit") +
  theme_classic() +
  xlab("Year") +
ylab("β-diversity") +
  facet_wrap(~Survey_Name_Season, ncol = 4, scales = "free") +
  theme(axis.text = element_text(size = 8), axis.title = element_text(size = 12))

ggsave(points_wavylines_bray_total_year_reduced_gam_individual_facet_25_42, path =  here::here("figures"), filename = "points_wavylines_bray_total_year_reduced_gam_individual_facet_25_42.png", height = 11, width = 9)

NA
NA

Region by region build up (for presentations)

#EBS ONLY (segue for chapter 3)
points_wavylines_bray_total_year_reduced_gam_colorbytrend_EBSonly <- ggplot() +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r[survey_unit == "EBS"], cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), size = 2, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt[survey_unit == "EBS"], cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt[survey_unit == "EBS"], cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
    scale_color_manual(values =  "#cbbfde", name = "Survey Unit") +
  scale_fill_manual(values =  "#cbbfde", guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])), y = c(0.49,0.95)) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_colorbytrend_EBSonly

ggsave(points_wavylines_bray_total_year_reduced_gam_colorbytrend_EBSonly, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_colorbytrend_EBSonly.jpg", height = 6, width = 11, unit = "in")



#just one region that's homogenizing (SEUS-summer)
points_wavylines_bray_total_year_reduced_gam_colorbytrend_seus_summer <- ggplot() +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r[survey_unit == "SEUS-summer"], cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), size = 2, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt[survey_unit == "SEUS-summer"], cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt[survey_unit == "SEUS-summer"], cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
    scale_color_manual(values =  "#e7ac5b", name = "Survey Unit") +
  scale_fill_manual(values =  "#e7ac5b", guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])), y = c(0.49,0.95)) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_colorbytrend_seus_summer

ggsave(points_wavylines_bray_total_year_reduced_gam_colorbytrend_seus_summer, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_colorbytrend_seus_summer.jpg", height = 6, width = 11, unit = "in")




#just one region that's differentiating and one that's homogenizing
points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summeronly <- ggplot() +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r[survey_unit %in% c("NZ-WCSI","SEUS-summer")], cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), size = 2, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer")], cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer")], cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
    scale_color_manual(values =  c("#e7ac5b","#91c874"), name = "Survey Unit") +
  scale_fill_manual(values =  c("#e7ac5b","#91c874"), guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])), y = c(0.49,0.95)) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summeronly

ggsave(points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summeronly, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summeronly.jpg", height = 6, width = 11, unit = "in")


#just three regions, another one that's stable, (NEUS-Fall)
points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summer_NEUSfallonly <- ggplot() +
  geom_point(data = na.omit(distances_dissimilarities_allyears.r[survey_unit %in% c("NZ-WCSI","SEUS-summer", "NEUS-Fall")], cols = "year_adj"),
             aes(x = year,
                 y = bray_curtis_dissimilarity_total_mean,
                 fill = Survey_Name_Season), size = 2, shape = 21, color = "white") +
    geom_line(data = na.omit(year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer", "NEUS-Fall")], cols = "year_adj"),
             aes(x = year,
                 y = bray_glm_mod_fit,
                 color = Survey_Name_Season)) +
  geom_ribbon(data = na.omit(year_survey_unit_expand.dt[survey_unit %in% c("NZ-WCSI","SEUS-summer", "NEUS-Fall")], cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill =  Survey_Name_Season), alpha=0.1) + #add standard error
    scale_color_manual(values =  c("#cbbfde","#e7ac5b", "#91c874"), name = "Survey Unit") +
  scale_fill_manual(values =  c("#cbbfde","#e7ac5b", "#91c874"), guide = "none") +
  theme_classic() +
  lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])), y = c(0.49,0.95)) +
  xlab("Year") +
ylab("β-diversity") +
  theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))

points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summer_NEUSfallonly

ggsave(points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summer_NEUSfallonly, path = here::here("figures"), filename ="points_wavylines_bray_total_year_reduced_gam_colorbytrend_NZ_WCSI_SEUS_summer_NEUSfallonly.jpg", height = 6, width = 11, unit = "in")

NA
NA
NA

Merge BC versus Year plot with GAMS and Region vs.Ā coefficient plot for LMs

START HERE

Is each survey better described by LM or by GAM?


# Function to compare GAM and linear model fits
compare_models <- function(subset_data) {
  # Fit GAM model with "fs" basis and single smooth term
  gam_model <- gam(bray_curtis_dissimilarity_total_mean ~ s(year, bs = "fs", m = 1), data = subset_data)
  
  # Fit linear model
  lm_model <- lm(bray_curtis_dissimilarity_total_mean ~ year, data = subset_data)
  
  # Calculate AICc values
  aicc_gam <- AICc(gam_model)
  aicc_lm <- AICc(lm_model)
  
  comparison <- ifelse((abs(aicc_gam-aicc_lm) < 2 | (aicc_gam == aicc_lm)),"Same",
                       ifelse(((abs(aicc_gam-aicc_lm) > 2 & (aicc_gam < aicc_lm))),"GAM",
                              ifelse(((abs(aicc_gam-aicc_lm) > 2 & (aicc_gam > aicc_lm))), "Linear",NA)))
  
   return(data.table(Survey_Name_Season = unique(subset_data$Survey_Name_Season)[1],
                    comparison = comparison,
                    aicc_gam = aicc_gam,
                    aicc_lm = aicc_lm))
}

GAM_LM_model_comparisons <- data.table()

# Compare models for each survey name and bind the results
for (i in 1:length(all_survey_names)) {
  GAM_LM_model_comparisons_single <- compare_models(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i]])
  GAM_LM_model_comparisons <- rbind(GAM_LM_model_comparisons, GAM_LM_model_comparisons_single)
}
Warning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NAWarning: Item 2 has 0 rows but longest item has 1; filled with NAWarning: Item 3 has 0 rows but longest item has 1; filled with NA
GAM_LM_model_comparisons

#round to 2 significant figures

#names of numeric columns
numeric_cols <- names(GAM_LM_model_comparisons)[sapply(GAM_LM_model_comparisons, is.numeric)]

# Apply signif() only to numeric columns
GAM_LM_model_comparisons[, (numeric_cols) := lapply(.SD, function(x) if (is.numeric(x)) signif(x, digits = 3) else x), .SDcols = numeric_cols]


View(GAM_LM_model_comparisons)

colnames(GAM_LM_model_comparisons) <- c("Survey","Model comparison", "GAM AICc","LM AICc")

fwrite(GAM_LM_model_comparisons, here::here("output","GAM_LM_model_comparisons.csv"))

SCRATCH OLD CODE These bar plots show LMER random slope and intercept and use alternate color schemes

BC_total_Dissimilarity_Coef_errorbar_reduced <- ggplot() +
    geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, fill = Directional_Change_sig, color = Directional_Change_sig), stat = 'identity', shape = 21) +
  scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length\n(years)") +
  geom_hline(yintercept = 0) +
  scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(colour = color_year_adj_order, face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.25,0.7), legend.direction = "vertical")

#pull legend for homogenization
directional_change_legend_plot <- BC_total_Dissimilarity_Coef_errorbar_reduced + 
  scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend") +
  scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend") +
  scale_size_binned(range = c(1,8), name = "Survey period length", guide = "none") +
  theme(legend.position = "right", legend.background = element_rect(fill= "transparent")) +
  guides(colour = guide_legend(override.aes = list(size=6)))


BC_total_Dissimilarity_Coef_errorbar_reduced

#ALT grey scale
BC_total_Dissimilarity_Coef_errorbar_reduced_greyscale <- ggplot() +
    geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, fill = Directional_Change_sig, color = Directional_Change_sig), stat = 'identity', shape = 21) +
  scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length\n(years)") +
  geom_hline(yintercept = 0) +
  scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.25,0.7), legend.direction = "vertical")

#"#73BA4D","#E0962C","#cbbfde"

BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend <- ggplot() +
    geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
  geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, color = Directional_Change_sig), stat = 'identity') +
  scale_color_manual(values = c("#73BA4D","#E0962C","#cbbfde"), name = "Dissimilarity trend", guide="none") +
  scale_size_binned(range = c(1,8), name = "Survey period length\n(years)") +
  geom_hline(yintercept = 0) +
  scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005",  "")) +
  xlab("Survey unit") +
  ylab("β-diversity trend") + #total BC dissimilarity trend
  coord_flip() +
  theme_classic() +
  theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.3,0.8), legend.direction = "vertical", legend.text = element_text(size = 15), legend.title = element_text(size = 16))

directional_change_legend_plot_colorbytrend <- BC_total_Dissimilarity_Coef_errorbar_reduced_colorbytrend + 
  theme(legend.position = "right", legend.background = element_rect(fill= "transparent"), 
         legend.text = element_text(size = 15), legend.title = element_text(size = 16)) +
  guides(colour = guide_legend(override.aes = list(size=6)), size = "none")

Merge BC versus Year plot with GAMS and Region vs. coefficient plot for LMs


<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuXG5CQ190b3RhbF9HQU1fTE1FUl9tZXJnZV9sZWdlbmQgPC0gZ2dkcmF3KHhsaW0gPSBjKDAsIDQwLjUpLCB5bGltID0gYygwLCAyMSkpICtcbiAgICBkcmF3X3Bsb3QocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAxLCB5ID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjApICtcbiAgICBkcmF3X3Bsb3QoQkNfdG90YWxfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWQgK1xuICAgICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplXG4gICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplXG4gICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMjAsIHkgPSAxLCB3aWR0aCA9MTksIGhlaWdodCA9IDIwKSArXG4gICAgZHJhd19wbG90KGdldF9sZWdlbmQoZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90ICsgXG4gICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplXG4gICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplXG4gICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTMpKSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDI3LCB5ID0gMTAsIHdpZHRoID0gMywgaGVpZ2h0ID0gMikgK1xuICBnZW9tX3RleHQoYWVzKHggPSAyLCB5ID0gMjAuNyksIGxhYmVsID0gKFwiYS5cIiksIHNpemUgPTgsIGZvbnRmYWNlID0gXCJib2xkXCIpICtcbiAgZ2VvbV90ZXh0KGFlcyh4ID0yMCwgeSA9IDIwLjcpLCBsYWJlbCA9IChcImIuXCIpLCBzaXplID04LCBmb250ZmFjZSA9IFwiYm9sZFwiKVxuXG5cbmdnc2F2ZShCQ190b3RhbF9HQU1fTE1FUl9tZXJnZV9sZWdlbmQsIHBhdGggPSBoZXJlOjpoZXJlKFwiZmlndXJlc1wiKSwgZmlsZW5hbWUgPSBcIkJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZC5wbmdcIiwgaGVpZ2h0ID0gOCwgd2lkdGggPSAxNCwgdW5pdHMgPSBcImluXCIpXG5cbiNBTFQgR1JFWSBTQ0FMRVxuQkNfdG90YWxfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kX2dyZXlzY2FsZSA8LSBnZ2RyYXcoeGxpbSA9IGMoMCwgNDAuNSksIHlsaW0gPSBjKDAsIDIxKSkgK1xuICAgIGRyYXdfcGxvdChwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9ncmV5c2NhbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAxLCB5ID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjApICtcbiAgICBkcmF3X3Bsb3QoQkNfdG90YWxfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWRfZ3JleXNjYWxlICtcbiAgICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZVxuICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZVxuICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDIwLCB5ID0gMSwgd2lkdGggPSAxOSwgaGVpZ2h0ID0gMjApICtcbiAgICBkcmF3X3Bsb3QoZ2V0X2xlZ2VuZChkaXJlY3Rpb25hbF9jaGFuZ2VfbGVnZW5kX3Bsb3QgKyBcbiAgICAgIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAnY20nKSwgI2NoYW5nZSBsZWdlbmQga2V5IHNpemVcbiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLCAjY2hhbmdlIGxlZ2VuZCB0aXRsZSBmb250IHNpemVcbiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMykpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAyNywgeSA9IDEwLCB3aWR0aCA9IDMsIGhlaWdodCA9IDIpICtcbiAgZ2VvbV90ZXh0KGFlcyh4ID0gMiwgeSA9IDIwLjcpLCBsYWJlbCA9IChcImEuXCIpLCBzaXplID04LCBmb250ZmFjZSA9IFwiYm9sZFwiKSArXG4gIGdlb21fdGV4dChhZXMoeCA9MjAsIHkgPSAyMC43KSwgbGFiZWwgPSAoXCJiLlwiKSwgc2l6ZSA9OCwgZm9udGZhY2UgPSBcImJvbGRcIilcblxuZ2dzYXZlKEJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9ncmV5c2NhbGUsIHBhdGggPSBoZXJlOjpoZXJlKFwiZmlndXJlc1wiKSwgZmlsZW5hbWUgPSBcIkJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9ncmV5c2NhbGUucG5nXCIsIGhlaWdodCA9IDgsIHdpZHRoID0gMTQsIHVuaXRzID0gXCJpblwiKVxuYGBgIn0= -->

```r

BC_total_GAM_LMER_merge_legend <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
    draw_plot(points_wavylines_bray_total_year_reduced_gam,
                                         x = 1, y = 1, width = 20, height = 20) +
    draw_plot(BC_total_Dissimilarity_Coef_errorbar_reduced +
        theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=16), #change legend title font size
        legend.text = element_text(size=14)), #change legend text font size),
                                         x = 20, y = 1, width =19, height = 20) +
    draw_plot(get_legend(directional_change_legend_plot + 
      theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=15), #change legend title font size
        legend.text = element_text(size=13))), #change legend text font size)
                                       x = 27, y = 10, width = 3, height = 2) +
  geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
  geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")


ggsave(BC_total_GAM_LMER_merge_legend, path = here::here("figures"), filename = "BC_total_GAM_LMER_merge_legend.png", height = 8, width = 14, units = "in")

#ALT GREY SCALE
BC_total_GAM_LMER_merge_legend_greyscale <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
    draw_plot(points_wavylines_bray_total_year_reduced_gam_greyscale,
                                         x = 1, y = 1, width = 20, height = 20) +
    draw_plot(BC_total_Dissimilarity_Coef_errorbar_reduced_greyscale +
        theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=16), #change legend title font size
        legend.text = element_text(size=14)), #change legend text font size),
                                         x = 20, y = 1, width = 19, height = 20) +
    draw_plot(get_legend(directional_change_legend_plot + 
      theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
        legend.title = element_text(size=15), #change legend title font size
        legend.text = element_text(size=13))), #change legend text font size)
                                x = 27, y = 10, width = 3, height = 2) +
  geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
  geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")

ggsave(BC_total_GAM_LMER_merge_legend_greyscale, path = here::here("figures"), filename = "BC_total_GAM_LMER_merge_legend_greyscale.png", height = 8, width = 14, units = "in")
LS0tCnRpdGxlOiAiRGlzc2ltaWxhcml0eSB0aW1lIHNlcmllcyBhbmFseXNpcyIKYXV0aG9yOiBab8OrIEouIEtpdGNoZWwKZGF0ZTogT2N0b2JlciAxNywgMjAyMwpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tClByaW1hcnkgc2NyaXB0IDRhIGZvciBLaXRjaGVsIGV0IGFsLiAyMDIzIGluIHByZXAgdGF4b25vbWljIGRpdmVyc2l0eSBtYW51c2NyaXB0LgoKYGBge3Igc2V0dXB9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeSh2ZWdhbikKbGlicmFyeShzZikKbGlicmFyeShjb25jYXZlbWFuKSAjcG9seWdvbiBhcm91bmQgcG9pbnRzCmxpYnJhcnkoYmV0YXBhcnQpICNhbGxvd3MgdXMgdG8gcGFydGl0aW9uIGJldGEgZGl2ZXJzaXR5CmxpYnJhcnkoZ2Vvc3BoZXJlKQpsaWJyYXJ5KGdncHVicikgI3N0YXRfcmVnbGluZV9lcXVhdGlvbgpsaWJyYXJ5KG5sbWUpCmxpYnJhcnkobWdjdikgI3RvIG1ha2UgZ2FtCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShsbWU0KQpsaWJyYXJ5KHN0cmluZ3IpCmBgYAoKUHVsbCBkaXNzaW1pbGFyaXR5IHRhYmxlCmBgYHtyIHB1bGwgb3V0cHV0cyBmcm9tIHByZXZpb3VzIHNjcmlwdHN9CiNQdWxsIERpc3NpbWlsYXJpdHkgTWVhbnMKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yIDwtIHJlYWRSRFMoaGVyZTo6aGVyZSgib3V0cHV0IiwgImRpc3NpbWlsYXJpdGllcyIsICJkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIucmRzIikpCgojbWFrZSBzdXJ2ZXkgYW5kIHN1cnZleSB1bml0IGZhY3RvcnMKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyxzdXJ2ZXk6PWZhY3RvcihzdXJ2ZXkpXVssc3VydmV5X3VuaXQ6PWZhY3RvcihzdXJ2ZXlfdW5pdCldCgojYWRqdXN0IHllYXJzCmRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl9hZGogOj0geWVhci1taW4oeWVhcikrMV0KCiNhZGQgbmV3IHZhcmlhYmxlIGZvciB5ZWFyIGluIHNlcXVlbmNlIHBlciByZWdpb24KZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyxmaXJzdF95ZWFyIDo9IG1pbih5ZWFyKSwuKHN1cnZleV91bml0KV0KZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyxsYXN0X3llYXIgOj0gbWF4KHllYXIpLC4oc3VydmV5X3VuaXQpXQoKI2Rpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl9pbl9zZXEgOj0geWVhci1maXJzdF95ZWFyKzFdCgpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJzX3NhbXBsZWQgOj0gbGFzdF95ZWFyLWZpcnN0X3llYXIrMV0KCgpgYGAKCiMjI1BhbGV0dGUgZm9yIFBsb3R0aW5nClBhbGV0dGUgZm9yIHBsb3R0aW5nIGFsbCA0MiBzdXJ2ZXkgdW5pdHMKYGBge3IgbGluayBjb2xvcnMgdG8gc3VydmV5IHVuaXRzfQpzdXJ2ZXlfdW5pdC5saXN0IDwtIGxldmVscyhmYWN0b3IoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyxzdXJ2ZXlfdW5pdF0pKQoKcGFsZXR0ZV80MiA8LSBjKAogICIjNUE1MTU2IiwgI0FJCiAgIiNERjAwREIiLCAjQklUUy0xCiAgIiNEQjhFREEiLCAjQklUUy00CiAgIiNGNjIyMkUiLCAjQ0hMCiAgIiNGOEExOUYiLCAjREZPLU5GCiAgIiMxNkZGMzIiLCAjREZPLVFDUwogICIjMzI1QTlCIiwgI0VCUwogICIjMzI4M0ZFIiwgI0VWSE9FCiAgIiNGRUFGMTYiLCAjRlItQ0dGUwogICIjZmNjYjZkIiwgI0dNRVgtRmFsbAogICIjMUM4MzU2IiwgI0dNRVgtU3VtbWVyCiAgIiNDNDQ1MUMiLCAjR09BCiAgIiM4NTY2MEQiLCAjR1JMLURFCiAgIiNCMDAwOUYiLCAjR1NMLU4KICAiI0JGNzlCOCIsICNHU0wtUwogICIjMUNCRTRGIiwgI0lDRS1HRlMKICAiIzc4MkFCNiIsICNJRS1JR0ZTCiAgIiM5MEFEMUMiLCAjTUVESVRTCiAgIiM2QjAwM0EiLCAjTkFNCiAgIiNBNzVCMDAiLCAjTkVVUy1GYWxsCiAgIiNFM0IwNzIiLCAjTkVVUy1TcHJpbmcKICAiIzAyRThCNiIsICNOSUdGUy0xCiAgIiM5N0U3RDUiLCAjTklHRlMtNAogICIjQjAwMDY4IiwgI05vci1CVFMtMwogICIjMDBCOUUzIiwgI05TLUlCVFMtMQogICIjOTVFMkY0IiwgI05TLUlCVFMtMwogICIjQjNDRTczIiwgI05aLUNIQVQKICAiIzY4OTUwMCIsICNOWi1FQ1NJCiAgIiMzNjRkMDIiLCNOWi1TVUJBCiAgIiNBQUY0MDAiLCAjTlotV0NTSQogICIjQUEwREZFIiwgI1BULUlCVFMKICAiIzdmOWViOCIsICNST0NLQUxMCiAgIiNGQTAwODciLCAjUy1HRU9SRwogICIjREVBMEZEIiwgI1NDUy1TdW1tZXIKICAiI0ZDRUY4OCIsICNTRVVTLWZhbGwKICAiI0E1OTQwNSIsICNTRVVTLXNwcmluZwogICIjRkNFMTAwIiwgI1NFVVMtc3VtbWVyCiAgIiM1NDQ1NjMiLCAjU1dDLUlCVFMtMQogICIjYTM3ZmM3IiwgI1NXQy1JQlRTLTQKICAiI0MwNzVBNiIsICNXQ0FOTgogICIjQkRDREZGIiwgI1pBRi1BVEwKICAiIzAwM0VGRiIgICNaQUYtSU5ECikKCmNvbG9yX2xpbmsgPC0gZGF0YS50YWJsZShzdXJ2ZXlfdW5pdCA9IHN1cnZleV91bml0Lmxpc3QsaGV4ID0gcGFsZXR0ZV80MikKYGBgCgpBZGQgbmFtZXMgZm9yIHBsb3R0aW5nCmBgYHtyIGFkZCBuYW1lcyBmb3IgcGxvdHRpbmd9CgpuYW1lX2hlbHBlciA8LSBkYXRhLnRhYmxlKFN1cnZleV9OYW1lX1NlYXNvbiA9IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFsZXV0aWFuIElzbGFuZHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFsdGljIFNlYSBRMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCYWx0aWMgU2VhIFE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ld2ZvdW5kbGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJRdWVlbiBDaGFybG90dGUgU291bmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRWFzdGVybiBCZXJpbmcgU2VhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJheSBvZiBCaXNjYXkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRW5nbGlzaCBDaGFubmVsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkd1bGYgb2YgTWV4aWNvIFN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHdWxmIG9mIEFsYXNrYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmVlbmxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTiBHdWxmIG9mIFN0LiBMYXdyZW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTIEd1bGYgb2YgU3QuIExhd3JlbmNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkljZWxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXJpc2ggU2VhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGl0ZXJyYW5lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFtaWJpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJORSBVUyBGYWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5FIFVTIFNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIElyZWxhbmQgUTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTiBJcmVsYW5kIFE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhcmVudHMgU2VhIE5vcndheSBRMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIFNlYSBRMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIFNlYSBRMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGF0aGFtIFJpc2UgTloiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRSBDb2FzdCBTIElzbGFuZCBOWiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXIENvYXN0IFMgSXNsYW5kIE5aIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBvcnR1Z2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlMgR2VvcmdpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2NvdGlhbiBTaGVsZiBTdW1tZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFIFVTIEZhbGwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFIFVTIFNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0UgVVMgU3VtbWVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXIENvYXN0IFVTIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBdGxhbnRpYyBPY2VhbiBaQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5kaWFuIE9jZWFuIFpBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUm9ja2FsbCBQbGF0ZWF1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTY290bGFuZCBTaGVsZiBTZWEgUTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNjb3RsYW5kIFNoZWxmIFNlYSBRNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFsa2xhbmQgSXNsYW5kcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3VsZiBvZiBNZXhpY28gRmFsbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFyZW50cyBTZWEgTm9yd2F5IFExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdWItQW50YXJjdGljIE5aIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTY290aWFuIFNoZWxmIFNwcmluZyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0ID0gYygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBSSIsICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCSVRTLTEiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCSVRTLTQiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDSEwiLCAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERk8tTkYiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERk8tUUNTIiwgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFQlMiLCAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFVkhPRSIsICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGUi1DR0ZTIiwgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTUVYLVN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR09BIiwgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1JMLURFIiwgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1NMLU4iLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1NMLVMiLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUNFLUdGUyIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUUtSUdGUyIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTUVESVRTIiwgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFNIiwgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVVUy1GYWxsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVVUy1TcHJpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5JR0ZTLTEiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5JR0ZTLTQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vci1CVFMtMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5TLUlCVFMtMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5TLUlCVFMtMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLUNIQVQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLUVDU0kiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLVdDU0kiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBULUlCVFMiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlMtR0VPUkciLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNDUy1TVU1NRVIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFVVMtZmFsbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFVVMtc3ByaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRVVTLXN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0NBTk4iLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWkFGLUFUTCIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWkFGLUlORCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUk9DS0FMTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1dDLUlCVFMtMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1dDLUlCVFMtNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRkFMSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR01FWC1GYWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3ItQlRTLTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLVNVQkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNDUy1TUFJJTkciCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSkKCgpjb2xvcl9saW5rIDwtIG5hbWVfaGVscGVyW2NvbG9yX2xpbmssIG9uID0gInN1cnZleV91bml0Il0KCiNzYXZlIHRvIHB1bGwgaW50byBvdGhlciBzY3JpcHRzCmZ3cml0ZShjb2xvcl9saW5rLCBoZXJlOjpoZXJlKCJvdXRwdXQiLCJjb2xvcl9saW5rLmNzdiIpKQpgYGAKCgojI01ha2UgR0FNcwoKQnJheSBDdXJ0aXMKYGBge3IgYnJheSBjdXJ0aXMgZ2Ftc30KYnJheV9jdXJ0aXNfdG90YWxfZ2FtIDwtIGdhbShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiB5ZWFyICsgcyhzdXJ2ZXlfdW5pdCwgeWVhciwgYnMgPSAiZnMiLCBtID0gMSksI3JhbmRvbSBzbW9vdGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgpgYGAKCkphY2NhcmQKYGBge3IgamFjY2FyZCBnYW1zfQpqYWNjYXJkX3RvdGFsX2dhbSA8LSBnYW0oamFjY2FyZF9kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiB5ZWFyICsgcyhzdXJ2ZXlfdW5pdCwgeWVhciwgYnMgPSAiZnMiLCBtID0gMSksI3JhbmRvbSBzbW9vdGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgpgYGAKCgojI01ha2UgTE1FUlMKCkJyYXkKKlRoZXNlIGFsbCBjb252ZXJnZWQqCmBgYHtyIGJyYXl9CiNydW5uaW5nIHdpdGggbG1lIGluc3RlYWQgb2YgbG1lciBnYXZlIHNhbWUgcmVzdWx0cywgYnV0IGFsbG93ZWQgZm9yIGNhbGN1bGF0aW9uIG9mIHAtdmFsdWUKYnJheV9jdXJ0aXNfdG90YWxfbG1lIDwtIGxtZShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiB5ZWFyX2FkaiwgcmFuZG9tID0gKH4xICsgeWVhcl9hZGp8c3VydmV5X3VuaXQpLGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgojYnV0IGFsc28gcnVuIHdpdGggbG1lciBmb3IgY29uZmludAojdG90YWwKYnJheV9jdXJ0aXNfdG90YWxfbG1lciA8LSBsbWVyKGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiB+IHllYXJfYWRqICsgKDEgKyB5ZWFyX2FkanxzdXJ2ZXlfdW5pdCksZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucikKCiNiYWxhbmNlZCAoZm9yIGNvbXBhcmlzb24gcGxvdCkKYnJheV9jdXJ0aXNfYmFsYW5jZWRfbG1lciA8LSBsbWVyKGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfYmFsYW5jZWRfbWVhbiB+IHllYXJfYWRqICsgKDEgKyB5ZWFyX2FkanxzdXJ2ZXlfdW5pdCksZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucikKCiNncmFkaWVudCAoZm9yIGNvbXBhcmlzb24gcGxvdCkKYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lciA8LSBsbWVyKGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbiB+IHllYXJfYWRqICsgKDEgKyB5ZWFyX2FkanxzdXJ2ZXlfdW5pdCksZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucikKCiNKYWNjYXJkIHRvdGFsIChmb3IgY29tcGFyaXNvbiBwbG90KQpqYWNjYXJkX3RvdGFsX2xtZXIgPC0gbG1lcihqYWNjYXJkX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiB+IHllYXJfYWRqICsgKDEgKyB5ZWFyX2FkanxzdXJ2ZXlfdW5pdCksZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucikKCgpzdW1tYXJ5KGJyYXlfY3VydGlzX3RvdGFsX2xtZSkKYW5vdmEoYnJheV9jdXJ0aXNfdG90YWxfbG1lKQoKYnJheV9jdXJ0aXNfdG90YWxfY29lZnMgPC0gZGF0YS50YWJsZShjb2VmKGJyYXlfY3VydGlzX3RvdGFsX2xtZSkpCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzWyxzdXJ2ZXlfdW5pdCA6PSByb3duYW1lcyhjb2VmKGJyYXlfY3VydGlzX3RvdGFsX2xtZSkpXVssWWVhciA6PSByb3VuZCh5ZWFyX2Fkaiw1KV1bLEludGVyY2VwdCA6PSByb3VuZChgKEludGVyY2VwdClgLDIpXQojVmlldyhicmF5X2N1cnRpc190b3RhbF9jb2VmcykKCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzIDwtIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzW2NvbG9yX2xpbmssIG9uID0gInN1cnZleV91bml0Il0KCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLmV4cCA8LSBicmF5X2N1cnRpc190b3RhbF9jb2Vmc1ssLihTdXJ2ZXlfTmFtZV9TZWFzb24sIEludGVyY2VwdCwgWWVhcildCgojZXhwb3J0IHRoaXMgdGFibGUKZndyaXRlKGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLmV4cCwgZmlsZSA9IGhlcmU6OmhlcmUoIm91dHB1dCIsImJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLmV4cC5jc3YiKSkKYGBgCgpBbHNvLCBidWlsZCBhIHNpbXBsZSBsaW5lYXIgbW9kZWwgd2l0aCBhbiBpbnRlcmFjdGlvbiAoaW5zdGVhZCBvZiByYW5kb20gc2xvcGUgYW5kIGludGVyY2VwdCBmb3Igc3VydmV5KQpUSElTIElTIEhPVyBXRSBDTEFTU0lGWSBTVVJWRVlTCmBgYHtyfQpicmF5X2N1cnRpc190b3RhbF9sbSA8LSBsbShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiB5ZWFyX2FkaipzdXJ2ZXlfdW5pdCxkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yKQoKYnJheV9jdXJ0aXNfdG90YWxfY29lZnMgPC0gZGF0YS50YWJsZShzdW1tYXJ5KGJyYXlfY3VydGlzX3RvdGFsX2xtKSRjb2VmZmljaWVudHMpCiAgYnJheV9jdXJ0aXNfdG90YWxfY29lZnNbLHZhciA6PSByb3duYW1lcyhzdW1tYXJ5KGJyYXlfY3VydGlzX3RvdGFsX2xtKSRjb2VmZmljaWVudHMpXQogIAogICNsaW1pdCB0byBpbnRlcmFjdGlvbnMgb25seSAoY2hlY2sgdGhpcyBpZiB0aGVyZSBhcmUgYW55IG1vZGVsIGNoYW5nZXMhKSByb3cgMiBhbmQgcm93cyA0NDo4NAogIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnIgPC0gYnJheV9jdXJ0aXNfdG90YWxfY29lZnNbYygyLDQ0Ojg0KSxdCiAgCiAgI2FkanVzdCBzdXJ2ZXkgdW5pdCBuYW1lIGJ5IGRlbGV0aW5nIGJlZ2lubmluZyBvZiBzdHJpbmcKICBicmF5X2N1cnRpc190b3RhbF9jb2Vmcy5yWyxzdXJ2ZXlfdW5pdCA6PSBzdWJzdHIodmFyLCAyMSwgc3RyX2xlbmd0aCh2YXIpKV1bdmFyID09ICJ5ZWFyX2FkaiIsc3VydmV5X3VuaXQgOj0gIkFJIl0KICAKICAjY2FsY3VsYXRlIGludGVyYWN0aW9uIGNvZWZmaWNpZW50cwogIEFJX2VzdGltYXRlIDwtIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnJbMSxFc3RpbWF0ZV0KICBicmF5X2N1cnRpc190b3RhbF9jb2Vmcy5yWzEsc3VydmV5X3VuaXRfY29lZmZpY2llbnQgOj0gQUlfZXN0aW1hdGVdCiAgYnJheV9jdXJ0aXNfdG90YWxfY29lZnMuclsyOjQyLHN1cnZleV91bml0X2NvZWZmaWNpZW50IDo9IChBSV9lc3RpbWF0ZSArIEVzdGltYXRlKV0KICAKICAjaG9tb2dlbml6aW5nIHZzIGRpZmZlcmVudGlhdGluZwogIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnJbLGRpZmZlcmVudGlhdGluZyA6PSBpZmVsc2UoKGBTdGQuIEVycm9yYDwgYWJzKHN1cnZleV91bml0X2NvZWZmaWNpZW50KSAmIHN1cnZleV91bml0X2NvZWZmaWNpZW50ID4gMCksMSwwKV1bLGhvbW9nZW5pemluZyA6PSBpZmVsc2UoKGBTdGQuIEVycm9yYDwgYWJzKHN1cnZleV91bml0X2NvZWZmaWNpZW50KSAmIHN1cnZleV91bml0X2NvZWZmaWNpZW50IDwgMCksMSwwKV0KICAKICAjbG93ZXIgYW5kIHVwcGVyIENJCiAgICBicmF5X2N1cnRpc190b3RhbF9jb2Vmcy5yWyxsd3IgOj0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQtYFN0ZC4gRXJyb3JgXVssdXByOj0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQrYFN0ZC4gRXJyb3JgXQogIAogIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzX3N1bSA8LSBkYXRhLnRhYmxlKGRpZmZlcmVudGlhdGluZyA9IHN1bSggIGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnIkZGlmZmVyZW50aWF0aW5nKSwgaG9tb2dlbml6aW5nID0gc3VtKCAgYnJheV9jdXJ0aXNfdG90YWxfY29lZnMuciRob21vZ2VuaXppbmcpKQogIAogICNoZXggYnkgdHJlbmQKICBicmF5X2N1cnRpc190b3RhbF9jb2Vmcy5yWyx0cmVuZF9jb2xvciA6PSBpZmVsc2UoaG9tb2dlbml6aW5nID09IDEsICIjZTdhYzViIiwgaWZlbHNlKGRpZmZlcmVudGlhdGluZyA9PSAxLCIjOTFjODc0IiwiI2NiYmZkZSIpKV0KICAKICAjbGluayB0byBjb2xvciBsaW5rCiAgYnJheV9jdXJ0aXNfdG90YWxfY29lZnMuciA8LSBjb2xvcl9saW5rW2JyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnIsIG9uID0gInN1cnZleV91bml0Il0KICAKICBicmF5X2N1cnRpc190b3RhbF9jb2Vmcy5yX2FscGhhIDwtIHNldG9yZGVyKGJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnIsIFN1cnZleV9OYW1lX1NlYXNvbikKICAKICBsaW5lYXJfbW9kZWxfY29sb3Jfb3JkZXIgPC0gc2V0b3JkZXIoYnJheV9jdXJ0aXNfdG90YWxfY29lZnMucl9hbHBoYVssLihTdXJ2ZXlfTmFtZV9TZWFzb24sdHJlbmRfY29sb3IpXSxTdXJ2ZXlfTmFtZV9TZWFzb24pCiAgCiAgI0ZBQ1RPUiBPUkRFUgogIGxpc3Rfc3VydmV5c19ieV9mYWN0b3IgPC0gbGV2ZWxzKGFzLmZhY3RvcihicmF5X2N1cnRpc190b3RhbF9jb2Vmcy5yX2FscGhhJFN1cnZleV9OYW1lX1NlYXNvbikpCgogIGxpbmVhcl9tb2RlbF9jb2xvcl9vcmRlcl9mYWN0b3JsZXZlbHM8LSBkYXRhLnRhYmxlKFN1cnZleV9OYW1lX1NlYXNvbiA9IGxpc3Rfc3VydmV5c19ieV9mYWN0b3IpCiAgICBsaW5lYXJfbW9kZWxfY29sb3Jfb3JkZXJfZmFjdG9ybGV2ZWxzPC1saW5lYXJfbW9kZWxfY29sb3Jfb3JkZXJbICBsaW5lYXJfbW9kZWxfY29sb3Jfb3JkZXJfZmFjdG9ybGV2ZWxzLCBvbiA9ICJTdXJ2ZXlfTmFtZV9TZWFzb24iXQpgYGAKCgpHZXQgTE1FUiBtb2RlbCBhcyBwcmVkaWN0aW9ucwpgYGB7ciBUT1RBTCBCQ30KCiMgbmVlZCB0byBzb3J0IG91dCB5ZWFyIGluIHNlcSB2ZXJzdXMgb3ZlcmFsbCB5ZWFyIG1vZGVscwojbmV3IGRhdGEgZm9yIGxtZXIKbG1lcl95ZWFyIDwtIHNlcShtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksIG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSwgYnkgPSAwLjEpCgpsbWVyX3llYXJfYWRqIDwtIHNlcShtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2Fkal0pLCBtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2Fkal0pLCBieSA9IDAuMSkKCiNwcmVkaWN0IGF2ZXJhZ2UgbG1lcgpsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMgPC0gZGF0YS50YWJsZSh5ZWFyID0gbG1lcl95ZWFyLCB5ZWFyX2FkaiA9IGxtZXJfeWVhcl9hZGopCgojY29uZmlkZW5jZSBpbnRlcnZhbHMKYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50IDwtIGNvbmZpbnQoYnJheV9jdXJ0aXNfdG90YWxfbG1lcikKCiNwb3B1bGF0ZSBkYXRhIHRhYmxlIG9mIGxtZXIgcHJlZGljdGlvbnMKbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzIDo9IGZpeGVmKGJyYXlfY3VydGlzX3RvdGFsX2xtZXIpW1sxXV0gKyBmaXhlZihicmF5X2N1cnRpc190b3RhbF9sbWVyKVtbMl1dICogeWVhcl9hZGpdWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0kgOj0gYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50WzVdICsgYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50WzZdICogeWVhcl9hZGpdWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kgOj0gYnJheV9jdXJ0aXNfdG90YWxfbG1lcl9jb25maW50WzExXSArIGJyYXlfY3VydGlzX3RvdGFsX2xtZXJfY29uZmludFsxMl0gKiB5ZWFyX2Fkal0KYGBgCgpgYGB7ciBCQUxBTkNFRCBCQ30KCiMgbmVlZCB0byBzb3J0IG91dCB5ZWFyIGluIHNlcSB2ZXJzdXMgb3ZlcmFsbCB5ZWFyIG1vZGVscwojbmV3IGRhdGEgZm9yIGxtZXIKCgojcHJlZGljdCBhdmVyYWdlIGxtZXIKbG1lcl9icmF5X2JhbGFuY2VkX3ByZWRpY3Rpb25zIDwtIGRhdGEudGFibGUoeWVhciA9IGxtZXJfeWVhciwgeWVhcl9hZGogPSBsbWVyX3llYXJfYWRqKQoKI2NvbmZpZGVuY2UgaW50ZXJ2YWxzCmJyYXlfY3VydGlzX2JhbGFuY2VkX2xtZXJfY29uZmludCA8LSBjb25maW50KGJyYXlfY3VydGlzX2JhbGFuY2VkX2xtZXIpCgojcG9wdWxhdGUgZGF0YSB0YWJsZSBvZiBsbWVyIHByZWRpY3Rpb25zCmxtZXJfYnJheV9iYWxhbmNlZF9wcmVkaWN0aW9uc1ssYnJheV9jdXJ0aXNfbG1lcl9wcmVkcyA6PSBmaXhlZihicmF5X2N1cnRpc19iYWxhbmNlZF9sbWVyKVtbMV1dICsgZml4ZWYoYnJheV9jdXJ0aXNfYmFsYW5jZWRfbG1lcilbWzJdXSAqIHllYXJfYWRqXVssYnJheV9jdXJ0aXNfbG1lcl9wcmVkc19sb3dlckNJIDo9IGJyYXlfY3VydGlzX2JhbGFuY2VkX2xtZXJfY29uZmludFs1XSArIGJyYXlfY3VydGlzX2JhbGFuY2VkX2xtZXJfY29uZmludFs2XSAqIHllYXJfYWRqXVssYnJheV9jdXJ0aXNfbG1lcl9wcmVkc191cHBlckNJIDo9IGJyYXlfY3VydGlzX2JhbGFuY2VkX2xtZXJfY29uZmludFsxMV0gKyBicmF5X2N1cnRpc19iYWxhbmNlZF9sbWVyX2NvbmZpbnRbMTJdICogeWVhcl9hZGpdCmBgYAoKYGBge3IgR1JBRElFTlQgQkN9CgojIG5lZWQgdG8gc29ydCBvdXQgeWVhciBpbiBzZXEgdmVyc3VzIG92ZXJhbGwgeWVhciBtb2RlbHMKCgojcHJlZGljdCBhdmVyYWdlIGxtZXIKbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zIDwtIGRhdGEudGFibGUoeWVhciA9IGxtZXJfeWVhciwgeWVhcl9hZGogPSBsbWVyX3llYXJfYWRqKQoKI2NvbmZpZGVuY2UgaW50ZXJ2YWxzCmJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXJfY29uZmludCA8LSBjb25maW50KGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXIpCgojcG9wdWxhdGUgZGF0YSB0YWJsZSBvZiBsbWVyIHByZWRpY3Rpb25zCmxtZXJfYnJheV9ncmFkaWVudF9wcmVkaWN0aW9uc1ssYnJheV9jdXJ0aXNfbG1lcl9wcmVkcyA6PSBmaXhlZihicmF5X2N1cnRpc19ncmFkaWVudF9sbWVyKVtbMV1dICsgZml4ZWYoYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcilbWzJdXSAqIHllYXJfYWRqXVssYnJheV9jdXJ0aXNfbG1lcl9wcmVkc19sb3dlckNJIDo9IGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXJfY29uZmludFs1XSArIGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXJfY29uZmludFs2XSAqIHllYXJfYWRqXVssYnJheV9jdXJ0aXNfbG1lcl9wcmVkc191cHBlckNJIDo9IGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXJfY29uZmludFsxMV0gKyBicmF5X2N1cnRpc19ncmFkaWVudF9sbWVyX2NvbmZpbnRbMTJdICogeWVhcl9hZGpdCmBgYAoKYGBge3IgdG90YWwgamFjY2FyZH0KCiMgbmVlZCB0byBzb3J0IG91dCB5ZWFyIGluIHNlcSB2ZXJzdXMgb3ZlcmFsbCB5ZWFyIG1vZGVscwoKCiNwcmVkaWN0IGF2ZXJhZ2UgbG1lcgpsbWVyX2phY2NhcmRfdG90YWxfcHJlZGljdGlvbnMgPC0gZGF0YS50YWJsZSh5ZWFyID0gbG1lcl95ZWFyLCB5ZWFyX2FkaiA9IGxtZXJfeWVhcl9hZGopCgojY29uZmlkZW5jZSBpbnRlcnZhbHMKamFjY2FyZF90b3RhbF9sbWVyX2NvbmZpbnQgPC0gY29uZmludChqYWNjYXJkX3RvdGFsX2xtZXIpCgojcG9wdWxhdGUgZGF0YSB0YWJsZSBvZiBsbWVyIHByZWRpY3Rpb25zCmxtZXJfamFjY2FyZF90b3RhbF9wcmVkaWN0aW9uc1ssamFjY2FyZF9sbWVyX3ByZWRzIDo9IGZpeGVmKGphY2NhcmRfdG90YWxfbG1lcilbWzFdXSArIGZpeGVmKGphY2NhcmRfdG90YWxfbG1lcilbWzJdXSAqIHllYXJfYWRqXVssamFjY2FyZF9sbWVyX3ByZWRzX2xvd2VyQ0kgOj0gamFjY2FyZF90b3RhbF9sbWVyX2NvbmZpbnRbNV0gKyBqYWNjYXJkX3RvdGFsX2xtZXJfY29uZmludFs2XSAqIHllYXJfYWRqXVssamFjY2FyZF9sbWVyX3ByZWRzX3VwcGVyQ0kgOj0gamFjY2FyZF90b3RhbF9sbWVyX2NvbmZpbnRbMTFdICsgamFjY2FyZF90b3RhbF9sbWVyX2NvbmZpbnRbMTJdICogeWVhcl9hZGpdCmBgYAoKIyMjTW92ZSBmb3J3YXJkIHdpdGggQnJheSBDdXJ0aXMgdG90YWwgKG90aGVycyB0byBzdXBwbGVtZW50LCBhbHRob3VnaCB3aWxsIGluY2x1ZGUgaW4gcGxvdCBiZWxvdykKQ29lZmZpY2llbnRzIGZvciBMTUVSIGJ5IHN1cnZleV91bml0CmBgYHtyfQojdW5pcXVlIHN1cnZleSB1bml0IHllYXIgY29tYm9zCnN1cnZleV91bml0X3NhbXBsaW5nX3llYXJzIDwtIHVuaXF1ZShkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLC4oc3VydmV5X3VuaXQsIHllYXJfYWRqLCB5ZWFyLCB5ZWFyc19zYW1wbGVkKV0pCgojanVzdCAjIHllYXJzCnN1cnZleV91bml0X3llYXJzIDwtIHVuaXF1ZShzdXJ2ZXlfdW5pdF9zYW1wbGluZ195ZWFyc1ssLihzdXJ2ZXlfdW5pdCwgeWVhcnNfc2FtcGxlZCldKQoKIyBzZWUgZ3JvdXAgY29lZmZpY2llbnRzCm1vZGVsX2NvZWZzX3JlZHVjZWQgPC0gZGF0YS50YWJsZSh0cmFuc2Zvcm0oYXMuZGF0YS5mcmFtZShyYW5lZihicmF5X2N1cnRpc190b3RhbF9sbWVyKSksIGx3ciA9IGNvbmR2YWwgLSAxLjk2KmNvbmRzZCwgdXByID0gY29uZHZhbCArIDEuOTYqY29uZHNkKSkKI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY5ODA1NTMyL2V4dHJhY3QtdGhlLWNvbmZpZGVuY2UtaW50ZXJ2YWxzLW9mLWxtZXItcmFuZG9tLWVmZmVjdHMtcGxvdHRlZC13aXRoLWRvdHBsb3RyYQoKCiNPTkxZIFNMT1BFUwptb2RlbF9jb2Vmc19yZWR1Y2VkIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRbdGVybSA9PSAieWVhcl9hZGoiLF0KCm1vZGVsX2NvZWZzX3JlZHVjZWRbLHN1cnZleV91bml0IDo9IGdycF1bLHllYXJfYWRqIDo9IGNvbmR2YWxdCgojbWVyZ2Ugd2l0aCBkdXJhdGlvbiBvZiBzdXJ2ZXkKbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGggPC0gbW9kZWxfY29lZnNfcmVkdWNlZFtzdXJ2ZXlfdW5pdF9zYW1wbGluZ195ZWFycywgb24gPSAic3VydmV5X3VuaXQiXQoKCm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoWyx5ZWFyc19zYW1wbGVkIDo9IGFzLm51bWVyaWMoeWVhcnNfc2FtcGxlZCldWyxEaXJlY3Rpb25hbF9DaGFuZ2UgOj0gaWZlbHNlKHllYXJfYWRqID4gMCwgIkRpZmZlcmVudGlhdGlvbiIsIkhvbW9nZW5pemF0aW9uIildCgojZG9lcyBpdCBjcm9zcyB6ZXJvPwptb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aFssc2lnbmlmaWNhbnQgOj0gaWZlbHNlKGx3ciA+MCAmIHVwcj4wLFQsaWZlbHNlKGx3cjwwICYgdXByPDAsVCxGKSldCgojc2lnbmlmaWNhbnQgZGlyZWN0aW9uYWwgY2hhbmdlCm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoWyxEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnIDo9IGlmZWxzZSh5ZWFyX2FkaiA+IDAgJiBzaWduaWZpY2FudCA9PSBULCAiRGlmZmVyZW50aWF0aW9uIixpZmVsc2UoeWVhcl9hZGogPCAwICYgc2lnbmlmaWNhbnQgPT0gVCwgIkhvbW9nZW5pemF0aW9uIiwgIk5vIHRyZW5kIGluXG5kaXNzaW1pbGFyaXR5IikpXQoKCiNtaW4gbWF4IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXMKbWluX2JyYXlfcmVkdWNlZCA8LSBtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyxicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW5dLCBuYS5ybSA9IFQpCm1heF9icmF5X3JlZHVjZWQgPC0gbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuXSwgbmEucm0gPSBUKQoKbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGggPC0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGhbY29sb3JfbGluaywgb24gPSAic3VydmV5X3VuaXQiXQoKI2RlbGV0ZSBhbnkgTkFzCm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoIDwtIG5hLm9taXQobW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGNvbHMgPSAic2lnbmlmaWNhbnQiKQoKI29yZGVyIHRhYmxlIGJ5IGNvZWZmaWNpZW50CnNldG9yZGVyKG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLCB5ZWFyX2FkaikKCkJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZSA8LSB1bmlxdWUobW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGhbLC4oY29uZHZhbCxjb25kc2QsIGx3ciwgdXByLCBzdXJ2ZXlfdW5pdCwgeWVhcl9hZGosIHllYXJzX3NhbXBsZWQsIERpcmVjdGlvbmFsX0NoYW5nZSwgaGV4LCBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpZ25pZmljYW50LCBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnKV0pIAoKI2V4dHJhY3QgY29sb3IgaGV4ZXMKI3llYXIgYWRqIGNvZWYgb3JkZXIKY29sb3JfeWVhcl9hZGpfb3JkZXIgPC0gQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlWyxoZXhdCgojYWxwaGFiZXRpY2FsIG9yZGVyCkJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZS5hbHBoYSA8LSBzZXRvcmRlcihCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUsIFN1cnZleV9OYW1lX1NlYXNvbikKCkJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZS5hbHBoYVssdHJlbmRfY29sb3IgOj0gaWZlbHNlKERpcmVjdGlvbmFsX0NoYW5nZV9zaWcgPT0gIkhvbW9nZW5pemF0aW9uIiwgIiNlN2FjNWIiLCBpZmVsc2UoRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZyA9PSAiRGlmZmVyZW50aWF0aW9uIiwiIzkxYzg3NCIsIiNjYmJmZGUiKSldCgpjb2xvcl9hbHBoYV9vcmRlciA8LSBCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGFbLGhleF0KY29sb3JfYWxwaGFfb3JkZXJfYnl0cmVuZCA8LSBCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGFbLCB0cmVuZF9jb2xvcl0KCiNrZXkgdHJlbmQgY29sb3IgYW5kIHN1cnZleQp0cmVuZF9jb2xvcl9zdXJ2ZXkgPC0gdW5pcXVlKEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZS5hbHBoYVssLihzdXJ2ZXlfdW5pdCwgU3VydmV5X05hbWVfU2Vhc29uLGhleCwgdHJlbmRfY29sb3IpXSkKCnNhdmVSRFMoQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLCBoZXJlOjpoZXJlKCJvdXRwdXQiLCJyZWdpb25fc3RhdHMiLCJCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuUmRzIikpCmBgYAoKQ29lZmZpY2llbnRzIGJ5IGludGVyYWN0aW9ucyBvZiBsaW5lYXIgbW9kZWwKYGBge3J9CiNleHRyYWN0IGNvbG9yIGhleGVzCiN5ZWFyIGFkaiBjb2VmIG9yZGVyCmNvbG9yX3llYXJfYWRqX29yZGVyIDwtIEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVssaGV4XQoKI2FscGhhYmV0aWNhbCBvcmRlcgpCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGEgPC0gc2V0b3JkZXIoQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLCBTdXJ2ZXlfTmFtZV9TZWFzb24pCgpCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGFbLHRyZW5kX2NvbG9yIDo9IGlmZWxzZShEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnID09ICJIb21vZ2VuaXphdGlvbiIsICIjZTdhYzViIiwgaWZlbHNlKERpcmVjdGlvbmFsX0NoYW5nZV9zaWcgPT0gIkRpZmZlcmVudGlhdGlvbiIsIiM5MWM4NzQiLCIjY2JiZmRlIikpXQoKY29sb3JfYWxwaGFfb3JkZXIgPC0gQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLmFscGhhWyxoZXhdCmNvbG9yX2FscGhhX29yZGVyX2J5dHJlbmQgPC0gQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLmFscGhhWywgdHJlbmRfY29sb3JdCgoja2V5IHRyZW5kIGNvbG9yIGFuZCBzdXJ2ZXkKdHJlbmRfY29sb3Jfc3VydmV5IDwtIHVuaXF1ZShCQ190b3RhbF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGFbLC4oc3VydmV5X3VuaXQsIFN1cnZleV9OYW1lX1NlYXNvbixoZXgsIHRyZW5kX2NvbG9yKV0pCgpzYXZlUkRTKEJDX3RvdGFsX21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZSwgaGVyZTo6aGVyZSgib3V0cHV0IiwicmVnaW9uX3N0YXRzIiwiQkNfdG90YWxfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLlJkcyIpKQpgYGAKCgpUb3RhbCB2ZXJzdXMgYmFsYW5jZWQgQkMgcGxvdApgYGB7cn0KZ2dwbG90KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucikgKwogIGdlb21fcG9pbnQoYWVzKGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwgYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9iYWxhbmNlZF9tZWFuKSkgKwogIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgaW50ZXJjcGV0ID0gMCkgKwogIGdlb21fc21vb3RoKGFlcyhicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sIGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfYmFsYW5jZWRfbWVhbikpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICJUb3RhbCBCQyBkaXNzaW1pbGFyaXR5IiwgIHkgPSAiQmFsYW5jZWQgY2hhbmdlcyBpbiBhYnVuZGFuY2UvYmlvbWFzcyIpCgpnZ3Bsb3QoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yKSArCiAgZ2VvbV9wb2ludChhZXMoYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLCBicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X2dyYWRpZW50X21lYW4pKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNwZXQgPSAwKSArCiAgZ2VvbV9zbW9vdGgoYWVzKGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwgYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9ncmFkaWVudF9tZWFuKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIlRvdGFsIEJDIGRpc3NpbWlsYXJpdHkiLCAgeSA9ICJBYnVuZGFuY2UvYmlvbWFzcyBncmFkaWVudCIpCgojYWxsIG9uIG9uZSBwbG90CiNyZWR1Y2VkCmRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuci5yIDwtIGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssLih5ZWFyLCBicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sIGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbiwgYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9iYWxhbmNlZF9tZWFuLCBqYWNjYXJkX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbildCgojd2lkZSB0byBsb25nCmRpc3NpbV9sb25nIDwtIG1lbHQoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLnIsIGlkLnZhcnMgPSBjKCJ5ZWFyIiksIHZhcmlhYmxlLm5hbWUgPSAiRGlzc2ltaWxhcml0eSBtZXRyaWMiKQoKZGlzc2ltX2xvbmdbLGBEaXNzaW1pbGFyaXR5IG1ldHJpY2AgOj0gZmFjdG9yKGBEaXNzaW1pbGFyaXR5IG1ldHJpY2AsIGxldmVscyA9IGMoICJicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4iLCJicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X2JhbGFuY2VkX21lYW4iLCJicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X2dyYWRpZW50X21lYW4iLCAiamFjY2FyZF9kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4iKSldCgpCQ19kaXNzaW1pbGFyaXR5X2NvbXBvbmVudHMgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRpc3NpbV9sb25nW2BEaXNzaW1pbGFyaXR5IG1ldHJpY2AgIT0gImphY2NhcmRfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuIixdLCBhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSBgRGlzc2ltaWxhcml0eSBtZXRyaWNgKSwgYWxwaGEgPSAwLjIsIHNpemUgPSAxKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IGxtZXJfYnJheV90b3RhbF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5bWluID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc19sb3dlckNJLCB5bWF4ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc191cHBlckNJKSwgZmlsbCA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAjYmFsYW5jZWQKICAgIGdlb21fcmliYm9uKGRhdGEgPSBsbWVyX2JyYXlfZ3JhZGllbnRfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeW1pbiA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfbG93ZXJDSSwgeW1heCA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfdXBwZXJDSSksIGZpbGwgPSAiY2FkZXRibHVlMyIsIGFscGhhID0gMC4zKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfZ3JhZGllbnRfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJjYWRldGJsdWUzIikgKwogICNncmFkaWVudAogICAgZ2VvbV9yaWJib24oZGF0YSA9IGxtZXJfYnJheV9iYWxhbmNlZF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5bWluID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc19sb3dlckNJLCB5bWF4ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc191cHBlckNJKSwgZmlsbCA9ICJkYXJrc2FsbW9uIiwgYWxwaGEgPSAwLjMpICsKICBnZW9tX2xpbmUoZGF0YSA9IGxtZXJfYnJheV9iYWxhbmNlZF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkcyksIGNvbG9yID0gImRhcmtzYWxtb24iKSArCiAgI2ZpeC4gY29sb3JzIG9mIHBvaW50cwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsImRhcmtzYWxtb24iLCJjYWRldGJsdWUzIiksIGxhYmVscyA9IGMoIlRvdGFsIiwiQmFsYW5jZWQgdmFyaWF0aW9uXG5pbiBhYnVuZGFuY2UiLCJCaW9tYXNzIGdyYWRpZW50IikpICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSAiVmFsdWUiKSArCiAgbGltcyh5ID0gYyhtaW4oZGlzc2ltX2xvbmckdmFsdWUpLCBtYXgoZGlzc2ltX2xvbmckdmFsdWUpKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjE3LDAuMzcpKQoKZ2dzYXZlKEJDX2Rpc3NpbWlsYXJpdHlfY29tcG9uZW50cywgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWU9KCJCQ19kaXNzaW1pbGFyaXR5X2NvbXBvbmVudHMuanBnIiksIHdpZHRoID0gNi41LCBoZWlnaHQgPSA1LCB1bml0cyA9ICJpbiIpCgojSmFjY2FyZApKYWNjYXJkX2Rpc3NpbWlsYXJpdHkgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRpc3NpbV9sb25nW2BEaXNzaW1pbGFyaXR5IG1ldHJpY2AgPT0gImphY2NhcmRfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuIl0sIGFlcyh4ID0geWVhciwgeSA9IHZhbHVlKSwgYWxwaGEgPSAwLjIsIHNpemUgPSAxKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IGxtZXJfamFjY2FyZF90b3RhbF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5bWluID0gamFjY2FyZF9sbWVyX3ByZWRzX2xvd2VyQ0ksIHltYXggPSBqYWNjYXJkX2xtZXJfcHJlZHNfdXBwZXJDSSksIGZpbGwgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogIGdlb21fbGluZShkYXRhID0gbG1lcl9qYWNjYXJkX3RvdGFsX3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBqYWNjYXJkX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSAiVG90YWwgSmFjY2FyZCBkaXNzaW1pbGFyaXR5IikgKwogIGxpbXMoeSA9IGMobWluKGRpc3NpbV9sb25nJHZhbHVlKSwgbWF4KGRpc3NpbV9sb25nJHZhbHVlKSkpICsKICB0aGVtZV9jbGFzc2ljKCkKCmdnc2F2ZShKYWNjYXJkX2Rpc3NpbWlsYXJpdHksIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lPSgiSmFjY2FyZF9kaXNzaW1pbGFyaXR5LmpwZyIpLCB3aWR0aCA9IDYuNSwgaGVpZ2h0ID0gNSwgdW5pdHMgPSAiaW4iKQoKI21lcmdlCmxpYnJhcnkoY293cGxvdCkKYWxsX2Rpc3NpbWlsYXJpdGllc19vdmVyX3RpbWUgPC0gcGxvdF9ncmlkKEJDX2Rpc3NpbWlsYXJpdHlfY29tcG9uZW50cyArIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKYWNjYXJkX2Rpc3NpbWlsYXJpdHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMiwgYWxpZ24gPSAiaHYiLCBsYWJlbHMgPSBjKCJhLiIsImIuIikpCgpnZ3NhdmUoYWxsX2Rpc3NpbWlsYXJpdGllc19vdmVyX3RpbWUsIGZpbGVuYW1lID0gImFsbF9kaXNzaW1pbGFyaXRpZXNfb3Zlcl90aW1lLmpwZyIsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIHdpZHRoID0gMTAsIGhlaWdodCA9IDQuNSwgdW5pdHMgPSAiaW4iKQoKICAKYGBgCgoKTG9sbGlwb3AgU0UgcGxvdCBieSBsaW5lYXIgdHJlbmQgZXhwZXJpZW5jZWQKCmBgYHtyfQoKIyMjIyMjIyMjIyMjIyMjCiNGT1IgTElORUFSIE1PREVMIElOU1RFQUQgT0YgTElORUFSIE1JWEVEIEVGRkVDVFMKIyMjIyMjIyMjIyMjIyMjCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnIgPC0gc3VydmV5X3VuaXRfeWVhcnNbYnJheV9jdXJ0aXNfdG90YWxfY29lZnMuciwgb249InN1cnZleV91bml0Il0KCmJyYXlfY3VydGlzX3RvdGFsX2NvZWZzLnJbLERpcmVjdGlvbmFsX0NoYW5nZV9zaWcgOj0gaWZlbHNlKGRpZmZlcmVudGlhdGluZyA+IDAsICJEaWZmZXJlbnRpYXRpb24iLGlmZWxzZShob21vZ2VuaXppbmcgPiAwICwgIkhvbW9nZW5pemF0aW9uIiwgIk5vIHRyZW5kIGluXG5kaXNzaW1pbGFyaXR5IikpXQoKKEJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2NvbG9yYnl0cmVuZF9MSU5FQVJfTU9ERUwgPC0gZ2dwbG90KCkgKwogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gYnJheV9jdXJ0aXNfdG90YWxfY29lZnMuciwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgc3VydmV5X3VuaXRfY29lZmZpY2llbnQpICwgeSA9IHN1cnZleV91bml0X2NvZWZmaWNpZW50LCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGZpbGwgPSAiZ3JleSIsIHdpZHRoID0gMCkgKyAjYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgZ2VvbV9wb2ludChkYXRhID0gYnJheV9jdXJ0aXNfdG90YWxfY29lZnMuciwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgc3VydmV5X3VuaXRfY29lZmZpY2llbnQpICwgeSA9IHN1cnZleV91bml0X2NvZWZmaWNpZW50LCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgc2l6ZSA9IHllYXJzX3NhbXBsZWQsIGNvbG9yID0gRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZyksIHN0YXQgPSAnaWRlbnRpdHknKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM3M0JBNEQiLCIjRTA5NjJDIiwiI2NiYmZkZSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9zaXplX2Jpbm5lZChyYW5nZSA9IGMoMSw4KSwgbmFtZSA9ICJTdXJ2ZXkgcGVyaW9kIGxlbmd0aFxuKHllYXJzKSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiAgI3NjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjdG90YWwgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjMsMC44KSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSkKCmdnc2F2ZShCQ190b3RhbF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZF9jb2xvcmJ5dHJlbmRfTElORUFSX01PREVMLCAKICAgICAgIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gIkJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2NvbG9yYnl0cmVuZF9MSU5FQVJfTU9ERUwuanBnIiwgaGVpZ2h0ID0gNywgd2lkdGggPSA3KQoKI1N0aWxsIG5lZWQgdG8gZWRpdApkaXJlY3Rpb25hbF9jaGFuZ2VfbGVnZW5kX3Bsb3RfY29sb3JieXRyZW5kIDwtIEJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2NvbG9yYnl0cmVuZF9MSU5FQVJfTU9ERUwgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSAidHJhbnNwYXJlbnQiKSwgCiAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NikpLCBzaXplID0gIm5vbmUiKQpgYGAKCgpXYXZ5IExpbmUgUGxvdCBmb3IgR0FNcwoKR2VuZXJhdGUgcHJlZGljdGVkIHZhbHVlcyAodGhpcyBkYXRhdGFibGUgd2lsbCBob2xkIGJvdGggamFjY2FyZCBhbmQgYnJheSBjdXJ0aXMpCmBgYHtyIGdlbmVyYXRlIHByZWRpY3RlZCB2YWx1ZXMgR0FNfQoKI2FkZCBjb2xvcnMgYW5kIG5hbWVzIHRvIGZ1bGwgZGlzc2ltaWxhcml0eSBkYXRhIHRhYmxlCmRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuciA8LSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbY29sb3JfbGluaywgb24gPSAic3VydmV5X3VuaXQiXQoKI2dlbmVyYXRlIG5ldyBkYXRhIHRvIHNtb290aCBsaW5lcyAobmVlZCB5ZWFyIGFuZCBzZWFzb24gc3VydmV5IGNvbWJpbmF0aW9ucykKeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQgPC0gZGF0YS50YWJsZShzdXJ2ZXlfdW5pdCA9IGFzLmNoYXJhY3RlcihOVUxMKSwgeWVhciA9IGFzLm51bWVyaWMoTlVMTCksIHllYXJfYWRqID0gYXMubnVtZXJpYyhOVUxMICkpCgpmb3IgKGkgaW4gMTpsZW5ndGgoc3VydmV5X3VuaXQubGlzdCkpIHsKICAjZ2VuZXJhdGUgeWVhciB2ZWN0b3JzCiAgc3VydmV5X3VuaXRfeWVhcnMgPC0gdW5pcXVlKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltzdXJ2ZXlfdW5pdCA9PSBzdXJ2ZXlfdW5pdC5saXN0W2ldLC4oc3VydmV5X3VuaXQsIHllYXIsIHllYXJfYWRqKV0pCiAgCiAgeWVhcnMgPC0gc2VxKG1pbihzdXJ2ZXlfdW5pdF95ZWFyc1sseWVhcl0pLCBtYXgoc3VydmV5X3VuaXRfeWVhcnNbLHllYXJdKSwgYnkgPSAwLjEpCiAgCiAgeWVhcl9hZGp1c3QgPC0gc2VxKG1pbihzdXJ2ZXlfdW5pdF95ZWFyc1sseWVhcl9hZGpdKSwgbWF4KHN1cnZleV91bml0X3llYXJzWyx5ZWFyX2Fkal0pLCBieSA9IDAuMSkKICAKICB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdF9hZGRpdGlvbiA8LSBkYXRhLnRhYmxlKHN1cnZleV91bml0ID0gc3VydmV5X3VuaXQubGlzdFtpXSwgeWVhciA9IHllYXJzLCB5ZWFyX2FkaiA9IHllYXJfYWRqdXN0KQogIAogIHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0IDwtIHJiaW5kKHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdF9hZGRpdGlvbikKfQoKI2FkZCBjb2xvcnMgYW5kIG5hbWVzIHRvIGZ1bGwgeWVhciBhbmQgc3VydmV5IHVuaXQgY29tYmluYXRpb24gdGFibGUKeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQgPC0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbY29sb3JfbGluaywgb24gPSAic3VydmV5X3VuaXQiXQpgYGAKCgpHZXQgbW9kZWwgYXMgcHJlZGljdGlvbnMKQnJheSBDdXJ0aXMKYGBge3J9CiNmb3IgcGxvdHRpbmcsIGdldCBtb2RlbCBhcyBwcmVkaWN0aW9ucwpicmF5X2N1cnRpc190b3RhbF9nYW1fcHJlZGljdGlvbnMgPC0gcHJlZGljdChicmF5X2N1cnRpc190b3RhbF9nYW0sIHNlLmZpdCA9IFRSVUUsIG5ld2RhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCkKCiNtZXJnZSBpbnRvIHRhYmxlCnllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0WyxicmF5X2dsbV9tb2RfZml0IDo9IGJyYXlfY3VydGlzX3RvdGFsX2dhbV9wcmVkaWN0aW9ucyRmaXRdWyxicmF5X2dsbV9tb2RfZml0X1NFIDo9IGJyYXlfY3VydGlzX3RvdGFsX2dhbV9wcmVkaWN0aW9ucyRzZS5maXRdCgpgYGAKCkphY2NhcmQKR2V0IG1vZGVsIGFzIHByZWRpY3Rpb25zCmBgYHtyfQojZm9yIHBsb3R0aW5nLCBnZXQgbW9kZWwgYXMgcHJlZGljdGlvbnMKamFjY2FyZF90b3RhbF9nYW1fcHJlZGljdGlvbnMgPC0gcHJlZGljdChqYWNjYXJkX3RvdGFsX2dhbSwgc2UuZml0ID0gVFJVRSwgbmV3ZGF0YSA9IHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0KQoKI21lcmdlIGludG8gdGFibGUKeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbLGphY2NhcmRfZ2xtX21vZF9maXQgOj0gamFjY2FyZF90b3RhbF9nYW1fcHJlZGljdGlvbnMkZml0XVssamFjY2FyZF9nbG1fbW9kX2ZpdF9TRSA6PSBqYWNjYXJkX3RvdGFsX2dhbV9wcmVkaWN0aW9ucyRzZS5maXRdCgpgYGAKCgpQcm9kdWNlIFBsb3Qgb2YgR0FNIGFuZCBtZWFuIExNRVIgbGluZQpgYGB7ciBwbG90IEdBTSBhbmQgbWVhbiBMTUVSIGxpbmVzfQpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9ub2xtZXIgPC0gZ2dwbG90KCkgKwogIyBnZW9tX3JpYmJvbihkYXRhID0gbG1lcl9icmF5X3RvdGFsX3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHltaW4gPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0ksIHltYXggPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kpLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMikgKwogIGdlb21fcG9pbnQoZGF0YSA9IG5hLm9taXQoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsY29scyA9ICJ5ZWFyX2FkaiIpLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LGNvbHMgPSAieWVhcl9hZGoiKSwgYWVzKHggPSB5ZWFyLCB5bWluPWJyYXlfZ2xtX21vZF9maXQtYnJheV9nbG1fbW9kX2ZpdF9TRSwgeW1heD1icmF5X2dsbV9tb2RfZml0K2JyYXlfZ2xtX21vZF9maXRfU0UsIGZpbGwgPSAgU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGE9MC4xKSArICNhZGQgc3RhbmRhcmQgZXJyb3IKICMgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgY29sb3JfYWxwaGFfb3JkZXIsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwKICAgICAgIHkgPSBjKDAuMTUsMC45KSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoInRvdGFsIEJDIGRpc3NpbWlsYXJpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fbm9sbWVyCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fbm9sbWVyLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX25vbG1lci5qcGciLCBoZWlnaHQgPSA1LCB3aWR0aCA9IDUsIHVuaXQgPSAiaW4iKQoKI3dpdGggbG1lcgoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW0gPC0gZ2dwbG90KCkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeW1pbiA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfbG93ZXJDSSwgeW1heCA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfdXBwZXJDSSksIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4zKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbmEub21pdChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIsIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNCwgc2l6ZSA9IDEsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNikgKwogIGdlb21fcmliYm9uKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBjb2xzID0gInllYXJfYWRqIiksIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgY29sb3JfYWxwaGFfb3JkZXIsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbQoKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtLmpwZyIsIGhlaWdodCA9IDYsIHdpZHRoID0gNiwgdW5pdCA9ICJpbiIpCgojQUxUCiNwbG90IGFsbCwgYnV0IHNhbWUgY29sb3Igc2NoZW1lIChncmV5KQpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9ncmV5c2NhbGUgPC0gZ2dwbG90KCkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeW1pbiA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfbG93ZXJDSSwgeW1heCA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHNfdXBwZXJDSSksIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC4zKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sCiAgICAgICAgICAgICAgICAgZmlsbCA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC40LCBzaXplID0gMSwgc2hhcGUgPSAyMSwgY29sb3IgPSAid2hpdGUiKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX3JpYmJvbihkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgZ2VvbV9saW5lKGRhdGEgPSBsbWVyX2JyYXlfdG90YWxfcHJlZGljdGlvbnMsIGFlcyh4ID0geWVhciwgeSA9IGJyYXlfY3VydGlzX2xtZXJfcHJlZHMpLCBjb2xvciA9ICJibGFjayIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgcmVwKCJibGFjayIsIHRpbWVzID0gbGVuZ3RoKHVuaXF1ZShkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIkU3VydmV5X05hbWVfU2Vhc29uKSkpLCBuYW1lID0gIlN1cnZleSBVbml0IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICByZXAoImJsYWNrIiwgdGltZXMgPSBsZW5ndGgodW5pcXVlKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuciRTdXJ2ZXlfTmFtZV9TZWFzb24pKSksIGd1aWRlID0gIm5vbmUiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsaW1zKHggPSBjKG1pbihkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSxtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSkpCiAgICAgICApICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2dyZXlzY2FsZS5qcGciLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDYsIHVuaXQgPSAiaW4iKQpgYGAKCgpBbHRlcm5hdGl2ZSwgY29sb3IgYnkgdHJlbmQKYGBge3IgY29sb3Igd2F2eSBsaW5lcyBieSB0cmVuZH0KCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IGxtZXJfYnJheV90b3RhbF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5bWluID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc19sb3dlckNJLCB5bWF4ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc191cHBlckNJKSwgZmlsbCA9ICJncmV5IiwgYWxwaGEgPSAwLjMpICsKICBnZW9tX3BvaW50KGRhdGEgPSBuYS5vbWl0KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuciwgY29scyA9ICJ5ZWFyX2FkaiIpLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4sCiAgICAgICAgICAgICAgICAgZmlsbCA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC40LCBzaXplID0gMSwgc2hhcGUgPSAyMSwgY29sb3IgPSAid2hpdGUiKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9nbG1fbW9kX2ZpdCwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC42KSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQsIGNvbHMgPSAieWVhcl9hZGoiKSwgYWVzKHggPSB5ZWFyLCB5bWluPWJyYXlfZ2xtX21vZF9maXQtYnJheV9nbG1fbW9kX2ZpdF9TRSwgeW1heD1icmF5X2dsbV9tb2RfZml0K2JyYXlfZ2xtX21vZF9maXRfU0UsIGZpbGwgPSAgU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGE9MC4xKSArICNhZGQgc3RhbmRhcmQgZXJyb3IKICBnZW9tX2xpbmUoZGF0YSA9IGxtZXJfYnJheV90b3RhbF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkcyksIGNvbG9yID0gImJsYWNrIikgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9ICAgIGxpbmVhcl9tb2RlbF9jb2xvcl9vcmRlcl9mYWN0b3JsZXZlbHMkdHJlbmRfY29sb3IsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gICAgbGluZWFyX21vZGVsX2NvbG9yX29yZGVyX2ZhY3RvcmxldmVscyR0cmVuZF9jb2xvciwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSkseSA9IGMoMC40OSwwLjk1KSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmQKCmdnc2F2ZShwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmQsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0icG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kLmpwZyIsIGhlaWdodCA9IDYsIHdpZHRoID0gMTEsIHVuaXQgPSAiaW4iKQoKI3NjYWxlIGNvbG9yIGlkZW50aXR5Cgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmRfc3F1aWdnbGVzb25seSA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbmEub21pdChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIsIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNCwgc2l6ZSA9IDEsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNikgKwogIGdlb21fcmliYm9uKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBjb2xzID0gInllYXJfYWRqIiksIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gICAgbGluZWFyX21vZGVsX2NvbG9yX29yZGVyX2ZhY3RvcmxldmVscyR0cmVuZF9jb2xvciwgbmFtZSA9ICJTdXJ2ZXkgVW5pdCIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSAgICBsaW5lYXJfbW9kZWxfY29sb3Jfb3JkZXJfZmFjdG9ybGV2ZWxzJHRyZW5kX2NvbG9yLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwgeSA9IGMoMC40OSwwLjk1KSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmRfc3F1aWdnbGVzb25seQoKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9zcXVpZ2dsZXNvbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9zcXVpZ2dsZXNvbmx5LmpwZyIsIGhlaWdodCA9IDYsIHdpZHRoID0gMTEsIHVuaXQgPSAiaW4iKQpgYGAKCkJDCmBgYHtyIHBsb3QgZWFjaCBpbmRlcGVuZGVudGx5fQojcGxvdCBlYWNoIGluZGVwZW5kZW50bHkgZm9yIHN1cHBsZW1lbnQKI2FsbCBzdXJ2ZXkgbmFtZXMgPSAKYWxsX3N1cnZleV9uYW1lcyA8LSBzb3J0KHVuaXF1ZShjb2xvcl9saW5rJFN1cnZleV9OYW1lX1NlYXNvbikpCgojc3BsaXQgaW50byAyIGFuZCB1c2UgZmFjZXQKI2ZpcnN0IDI0CnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWxfZmFjZXRfMV8yNCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW1N1cnZleV9OYW1lX1NlYXNvbiAgJWluJSBhbGxfc3VydmV5X25hbWVzW2MoMToyNCldXSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuKSwgYWxwaGEgPSAwLjcpICsKICAgIGdlb21fbGluZShkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbU3VydmV5X05hbWVfU2Vhc29uICAgJWluJSBhbGxfc3VydmV5X25hbWVzW2MoMToyNCldXSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9nbG1fbW9kX2ZpdCkpICsKICBnZW9tX3JpYmJvbihkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbU3VydmV5X05hbWVfU2Vhc29uICAlaW4lIGFsbF9zdXJ2ZXlfbmFtZXNbYygxOjI0KV1dLAphZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSksIGFscGhhPTAuNSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgICBnZW9tX3Ntb290aChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW1N1cnZleV9OYW1lX1NlYXNvbiAgJWluJSBhbGxfc3VydmV5X25hbWVzW2MoMToyNCldXSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNCwgbWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMC41KSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gICAgbGluZWFyX21vZGVsX2NvbG9yX29yZGVyX2ZhY3RvcmxldmVscyR0cmVuZF9jb2xvclsxOjI0XSwgbmFtZSA9ICJTdXJ2ZXkgVW5pdCIpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICAgIGxpbmVhcl9tb2RlbF9jb2xvcl9vcmRlcl9mYWN0b3JsZXZlbHMkdHJlbmRfY29sb3JbMToyNF0sIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgZmFjZXRfd3JhcCh+U3VydmV5X05hbWVfU2Vhc29uLCBuY29sID0gNCwgc2NhbGVzID0gImZyZWUiKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBsZWdlbmQucG9zaXRpb24gPSAibnVsbCIpCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbF9mYWNldF8xXzI0LCBwYXRoID0gIGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAicG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbF9mYWNldF8xXzI0LnBuZyIsIGhlaWdodCA9IDExLCB3aWR0aCA9IDkpCgojc2Vjb25kIGhhbGYKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yX3NlY29uZCA8LSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbU3VydmV5X05hbWVfU2Vhc29uICAlaW4lIGFsbF9zdXJ2ZXlfbmFtZXNbYygyNTo0MildXQpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJfc2Vjb25kIDwtIHNldG9yZGVyKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucl9zZWNvbmQsU3VydmV5X05hbWVfU2Vhc29uKQp5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdF9zZWNvbmQgPC0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbU3VydmV5X05hbWVfU2Vhc29uICAgJWluJSBhbGxfc3VydmV5X25hbWVzW2MoMjU6NDIpXV0KeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRfc2Vjb25kIDwtIHNldG9yZGVyKHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0X3NlY29uZCwgU3VydmV5X05hbWVfU2Vhc29uKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbF9mYWNldF8yNV80MiA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yX3NlY29uZCwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuKSwgYWxwaGEgPSAwLjcpICsKICAgIGdlb21fbGluZShkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRfc2Vjb25kLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0KSkgKwogIGdlb21fcmliYm9uKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdF9zZWNvbmQsCmFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFKSwgYWxwaGE9MC41KSArICNhZGQgc3RhbmRhcmQgZXJyb3IKICBnZW9tX3Ntb290aChkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yX3NlY29uZCwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNCwgbWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMC41KSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gICAgbGluZWFyX21vZGVsX2NvbG9yX29yZGVyX2ZhY3RvcmxldmVscyR0cmVuZF9jb2xvclsyNTo0Ml0sIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSAgICBsaW5lYXJfbW9kZWxfY29sb3Jfb3JkZXJfZmFjdG9ybGV2ZWxzJHRyZW5kX2NvbG9yWzI1OjQyXSwgbmFtZSA9ICJTdXJ2ZXkgVW5pdCIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIG5jb2wgPSA0LCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbF9mYWNldF8yNV80MiwgcGF0aCA9ICBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gInBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWxfZmFjZXRfMjVfNDIucG5nIiwgaGVpZ2h0ID0gMTEsIHdpZHRoID0gOSkKCgpgYGAKCgpSZWdpb24gYnkgcmVnaW9uIGJ1aWxkIHVwIChmb3IgcHJlc2VudGF0aW9ucykKYGBge3IgcmVnaW9uIGJ1aWxkIHVwfQojRUJTIE9OTFkgKHNlZ3VlIGZvciBjaGFwdGVyIDMpCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9FQlNvbmx5IDwtIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBuYS5vbWl0KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltzdXJ2ZXlfdW5pdCA9PSAiRUJTIl0sIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBzaXplID0gMiwgc2hhcGUgPSAyMSwgY29sb3IgPSAid2hpdGUiKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbc3VydmV5X3VuaXQgPT0gIkVCUyJdLCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbc3VydmV5X3VuaXQgPT0gIkVCUyJdLCBjb2xzID0gInllYXJfYWRqIiksIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gICIjY2JiZmRlIiwgbmFtZSA9ICJTdXJ2ZXkgVW5pdCIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSAgIiNjYmJmZGUiLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwgeSA9IGMoMC40OSwwLjk1KSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmRfRUJTb25seQoKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9FQlNvbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9FQlNvbmx5LmpwZyIsIGhlaWdodCA9IDYsIHdpZHRoID0gMTEsIHVuaXQgPSAiaW4iKQoKCiNqdXN0IG9uZSByZWdpb24gdGhhdCdzIGhvbW9nZW5pemluZyAoU0VVUy1zdW1tZXIpCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9zZXVzX3N1bW1lciA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbmEub21pdChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbc3VydmV5X3VuaXQgPT0gIlNFVVMtc3VtbWVyIl0sIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBzaXplID0gMiwgc2hhcGUgPSAyMSwgY29sb3IgPSAid2hpdGUiKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbc3VydmV5X3VuaXQgPT0gIlNFVVMtc3VtbWVyIl0sIGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9nbG1fbW9kX2ZpdCwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbikpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbmEub21pdCh5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFtzdXJ2ZXlfdW5pdCA9PSAiU0VVUy1zdW1tZXIiXSwgY29scyA9ICJ5ZWFyX2FkaiIpLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSwgZmlsbCA9ICBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYT0wLjEpICsgI2FkZCBzdGFuZGFyZCBlcnJvcgogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9ICAiI2U3YWM1YiIsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gICIjZTdhYzViIiwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksIHkgPSBjKDAuNDksMC45NSkpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kX3NldXNfc3VtbWVyCgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kX3NldXNfc3VtbWVyLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9zZXVzX3N1bW1lci5qcGciLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDExLCB1bml0ID0gImluIikKCgoKI2p1c3Qgb25lIHJlZ2lvbiB0aGF0J3MgZGlmZmVyZW50aWF0aW5nIGFuZCBvbmUgdGhhdCdzIGhvbW9nZW5pemluZwpwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmRfTlpfV0NTSV9TRVVTX3N1bW1lcm9ubHkgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IG5hLm9taXQoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW3N1cnZleV91bml0ICVpbiUgYygiTlotV0NTSSIsIlNFVVMtc3VtbWVyIildLCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwKICAgICAgICAgICAgICAgICBmaWxsID0gU3VydmV5X05hbWVfU2Vhc29uKSwgc2l6ZSA9IDIsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0W3N1cnZleV91bml0ICVpbiUgYygiTlotV0NTSSIsIlNFVVMtc3VtbWVyIildLCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfZ2xtX21vZF9maXQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IG5hLm9taXQoeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbc3VydmV5X3VuaXQgJWluJSBjKCJOWi1XQ1NJIiwiU0VVUy1zdW1tZXIiKV0sIGNvbHMgPSAieWVhcl9hZGoiKSwgYWVzKHggPSB5ZWFyLCB5bWluPWJyYXlfZ2xtX21vZF9maXQtYnJheV9nbG1fbW9kX2ZpdF9TRSwgeW1heD1icmF5X2dsbV9tb2RfZml0K2JyYXlfZ2xtX21vZF9maXRfU0UsIGZpbGwgPSAgU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGE9MC4xKSArICNhZGQgc3RhbmRhcmQgZXJyb3IKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgYygiI2U3YWM1YiIsIiM5MWM4NzQiKSwgbmFtZSA9ICJTdXJ2ZXkgVW5pdCIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSAgYygiI2U3YWM1YiIsIiM5MWM4NzQiKSwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksIHkgPSBjKDAuNDksMC45NSkpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kX05aX1dDU0lfU0VVU19zdW1tZXJvbmx5CgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kX05aX1dDU0lfU0VVU19zdW1tZXJvbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9OWl9XQ1NJX1NFVVNfc3VtbWVyb25seS5qcGciLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDExLCB1bml0ID0gImluIikKCiNqdXN0IHRocmVlIHJlZ2lvbnMsIGFub3RoZXIgb25lIHRoYXQncyBzdGFibGUsIChORVVTLUZhbGwpCnBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9OWl9XQ1NJX1NFVVNfc3VtbWVyX05FVVNmYWxsb25seSA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbmEub21pdChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbc3VydmV5X3VuaXQgJWluJSBjKCJOWi1XQ1NJIiwiU0VVUy1zdW1tZXIiLCAiTkVVUy1GYWxsIildLCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfdG90YWxfbWVhbiwKICAgICAgICAgICAgICAgICBmaWxsID0gU3VydmV5X05hbWVfU2Vhc29uKSwgc2l6ZSA9IDIsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0W3N1cnZleV91bml0ICVpbiUgYygiTlotV0NTSSIsIlNFVVMtc3VtbWVyIiwgIk5FVVMtRmFsbCIpXSwgY29scyA9ICJ5ZWFyX2FkaiIpLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0W3N1cnZleV91bml0ICVpbiUgYygiTlotV0NTSSIsIlNFVVMtc3VtbWVyIiwgIk5FVVMtRmFsbCIpXSwgY29scyA9ICJ5ZWFyX2FkaiIpLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSwgZmlsbCA9ICBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYT0wLjEpICsgI2FkZCBzdGFuZGFyZCBlcnJvcgogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9ICBjKCIjY2JiZmRlIiwiI2U3YWM1YiIsICIjOTFjODc0IiksIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIGMoIiNjYmJmZGUiLCIjZTdhYzViIiwgIiM5MWM4NzQiKSwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksIHkgPSBjKDAuNDksMC45NSkpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kX05aX1dDU0lfU0VVU19zdW1tZXJfTkVVU2ZhbGxvbmx5CgpnZ3NhdmUocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kX05aX1dDU0lfU0VVU19zdW1tZXJfTkVVU2ZhbGxvbmx5LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9InBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZF9OWl9XQ1NJX1NFVVNfc3VtbWVyX05FVVNmYWxsb25seS5qcGciLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDExLCB1bml0ID0gImluIikKCgoKYGBgCgpNZXJnZSBCQyB2ZXJzdXMgWWVhciBwbG90IHdpdGggR0FNUyBhbmQgUmVnaW9uIHZzLiBjb2VmZmljaWVudCBwbG90IGZvciBMTXMKCmBgYHtyfQojQUxUIENPTE9SIEJZIFRSRU5ECkJDX3RvdGFsX0dBTV9MTV9tZXJnZV9sZWdlbmRfY29sb3JieXRyZW5kIDwtIGdnZHJhdyh4bGltID0gYygwLCA0MC41KSwgeWxpbSA9IGMoMCwgMjEpKSArCiAgICBkcmF3X3Bsb3QocG9pbnRzX3dhdnlsaW5lc19icmF5X3RvdGFsX3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAxLCB5ID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjApICsKICAgIGRyYXdfcGxvdChCQ190b3RhbF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZF9jb2xvcmJ5dHJlbmRfTElORUFSX01PREVMICsKICAgICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplCiAgICAgICAjIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplCiAgICAgICAjIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpCiAgICAgICApLCAjY2hhbmdlIGxlZ2VuZCB0ZXh0IGZvbnQgc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDIwLCB5ID0gMSwgd2lkdGggPSAxOSwgaGVpZ2h0ID0gMjApICsKICAgIGRyYXdfcGxvdChnZXRfbGVnZW5kKGRpcmVjdGlvbmFsX2NoYW5nZV9sZWdlbmRfcGxvdF9jb2xvcmJ5dHJlbmQgKyAKICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNSkpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDI3LCB5ID0gOCwgd2lkdGggPSAzLCBoZWlnaHQgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMiwgeSA9IDIwLjcpLCBsYWJlbCA9ICgiYS4iKSwgc2l6ZSA9OCwgZm9udGZhY2UgPSAiYm9sZCIpICsKICBnZW9tX3RleHQoYWVzKHggPTIwLCB5ID0gMjAuNyksIGxhYmVsID0gKCJiLiIpLCBzaXplID04LCBmb250ZmFjZSA9ICJib2xkIikKCmdnc2F2ZShCQ190b3RhbF9HQU1fTE1fbWVyZ2VfbGVnZW5kX2NvbG9yYnl0cmVuZCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAiQkNfdG90YWxfR0FNX0xNX21lcmdlX2xlZ2VuZF9jb2xvcmJ5dHJlbmQucG5nIiwgaGVpZ2h0ID0gOCwgd2lkdGggPSAxNCwgdW5pdHMgPSAiaW4iKQoKYGBgClNUQVJUIEhFUkUKCklzIGVhY2ggc3VydmV5IGJldHRlciBkZXNjcmliZWQgYnkgTE0gb3IgYnkgR0FNPwpgYGB7cn0KCiMgRnVuY3Rpb24gdG8gY29tcGFyZSBHQU0gYW5kIGxpbmVhciBtb2RlbCBmaXRzCmNvbXBhcmVfbW9kZWxzIDwtIGZ1bmN0aW9uKHN1YnNldF9kYXRhKSB7CiAgIyBGaXQgR0FNIG1vZGVsIHdpdGggImZzIiBiYXNpcyBhbmQgc2luZ2xlIHNtb290aCB0ZXJtCiAgZ2FtX21vZGVsIDwtIGdhbShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X3RvdGFsX21lYW4gfiBzKHllYXIsIGJzID0gImZzIiwgbSA9IDEpLCBkYXRhID0gc3Vic2V0X2RhdGEpCiAgCiAgIyBGaXQgbGluZWFyIG1vZGVsCiAgbG1fbW9kZWwgPC0gbG0oYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV90b3RhbF9tZWFuIH4geWVhciwgZGF0YSA9IHN1YnNldF9kYXRhKQogIAogICMgQ2FsY3VsYXRlIEFJQ2MgdmFsdWVzCiAgYWljY19nYW0gPC0gQUlDYyhnYW1fbW9kZWwpCiAgYWljY19sbSA8LSBBSUNjKGxtX21vZGVsKQogIAogIGNvbXBhcmlzb24gPC0gaWZlbHNlKChhYnMoYWljY19nYW0tYWljY19sbSkgPCAyIHwgKGFpY2NfZ2FtID09IGFpY2NfbG0pKSwiU2FtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCgoYWJzKGFpY2NfZ2FtLWFpY2NfbG0pID4gMiAmIChhaWNjX2dhbSA8IGFpY2NfbG0pKSksIkdBTSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSgoKGFicyhhaWNjX2dhbS1haWNjX2xtKSA+IDIgJiAoYWljY19nYW0gPiBhaWNjX2xtKSkpLCAiTGluZWFyIixOQSkpKQogIAogICByZXR1cm4oZGF0YS50YWJsZShTdXJ2ZXlfTmFtZV9TZWFzb24gPSB1bmlxdWUoc3Vic2V0X2RhdGEkU3VydmV5X05hbWVfU2Vhc29uKVsxXSwKICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29uID0gY29tcGFyaXNvbiwKICAgICAgICAgICAgICAgICAgICBhaWNjX2dhbSA9IGFpY2NfZ2FtLAogICAgICAgICAgICAgICAgICAgIGFpY2NfbG0gPSBhaWNjX2xtKSkKfQoKR0FNX0xNX21vZGVsX2NvbXBhcmlzb25zIDwtIGRhdGEudGFibGUoKQoKIyBDb21wYXJlIG1vZGVscyBmb3IgZWFjaCBzdXJ2ZXkgbmFtZSBhbmQgYmluZCB0aGUgcmVzdWx0cwpmb3IgKGkgaW4gMTpsZW5ndGgoYWxsX3N1cnZleV9uYW1lcykpIHsKICBHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnNfc2luZ2xlIDwtIGNvbXBhcmVfbW9kZWxzKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gYWxsX3N1cnZleV9uYW1lc1tpXV0pCiAgR0FNX0xNX21vZGVsX2NvbXBhcmlzb25zIDwtIHJiaW5kKEdBTV9MTV9tb2RlbF9jb21wYXJpc29ucywgR0FNX0xNX21vZGVsX2NvbXBhcmlzb25zX3NpbmdsZSkKfQoKR0FNX0xNX21vZGVsX2NvbXBhcmlzb25zCgojcm91bmQgdG8gMiBzaWduaWZpY2FudCBmaWd1cmVzCgojbmFtZXMgb2YgbnVtZXJpYyBjb2x1bW5zCm51bWVyaWNfY29scyA8LSBuYW1lcyhHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnMpW3NhcHBseShHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnMsIGlzLm51bWVyaWMpXQoKIyBBcHBseSBzaWduaWYoKSBvbmx5IHRvIG51bWVyaWMgY29sdW1ucwpHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnNbLCAobnVtZXJpY19jb2xzKSA6PSBsYXBwbHkoLlNELCBmdW5jdGlvbih4KSBpZiAoaXMubnVtZXJpYyh4KSkgc2lnbmlmKHgsIGRpZ2l0cyA9IDMpIGVsc2UgeCksIC5TRGNvbHMgPSBudW1lcmljX2NvbHNdCgoKVmlldyhHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnMpCgpjb2xuYW1lcyhHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnMpIDwtIGMoIlN1cnZleSIsIk1vZGVsIGNvbXBhcmlzb24iLCAiR0FNIEFJQ2MiLCJMTSBBSUNjIikKCmZ3cml0ZShHQU1fTE1fbW9kZWxfY29tcGFyaXNvbnMsIGhlcmU6OmhlcmUoIm91dHB1dCIsIkdBTV9MTV9tb2RlbF9jb21wYXJpc29ucy5jc3YiKSkKYGBgCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKU0NSQVRDSCBPTEQgQ09ERQpUaGVzZSBiYXIgcGxvdHMgc2hvdyBMTUVSIHJhbmRvbSBzbG9wZSBhbmQgaW50ZXJjZXB0IGFuZCB1c2UgYWx0ZXJuYXRlIGNvbG9yIHNjaGVtZXMKYGBge3IgYmFyIHBsb3Qgb2YgY29lZmZpY2llbnRzfQpCQ190b3RhbF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZCA8LSBnZ3Bsb3QoKSArCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGZpbGwgPSAiZ3JleSIsIHdpZHRoID0gMCkgKyAjYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgZ2VvbV9wb2ludChkYXRhID0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGFlcyh4ID0gcmVvcmRlcihTdXJ2ZXlfTmFtZV9TZWFzb24sIHllYXJfYWRqKSAsIHkgPSB5ZWFyX2FkaiwgbGFiZWwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpemUgPSB5ZWFyc19zYW1wbGVkLCBmaWxsID0gRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZywgY29sb3IgPSBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnKSwgc3RhdCA9ICdpZGVudGl0eScsIHNoYXBlID0gMjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmxhY2siLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIiwgZ3VpZGU9Im5vbmUiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGhcbih5ZWFycykiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjdG90YWwgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBjb2xvcl95ZWFyX2Fkal9vcmRlciwgZmFjZSA9ICJib2xkIiksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yNSwwLjcpLCBsZWdlbmQuZGlyZWN0aW9uID0gInZlcnRpY2FsIikKCiNwdWxsIGxlZ2VuZCBmb3IgaG9tb2dlbml6YXRpb24KZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90IDwtIEJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygid2hpdGUiLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGgiLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9ICJ0cmFuc3BhcmVudCIpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NikpKQoKCkJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkCgojQUxUIGdyZXkgc2NhbGUKQkNfdG90YWxfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWRfZ3JleXNjYWxlIDwtIGdncGxvdCgpICsKICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLCBhZXMoeCA9IHJlb3JkZXIoU3VydmV5X05hbWVfU2Vhc29uLCB5ZWFyX2FkaikgLCB5ID0geWVhcl9hZGosIGxhYmVsID0gU3VydmV5X05hbWVfU2Vhc29uLCB5bWluID0gbHdyLCB5bWF4ID0gdXByKSwgZmlsbCA9ICJncmV5Iiwgd2lkdGggPSAwKSArICNhZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMKICBnZW9tX3BvaW50KGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgc2l6ZSA9IHllYXJzX3NhbXBsZWQsIGZpbGwgPSBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnLCBjb2xvciA9IERpcmVjdGlvbmFsX0NoYW5nZV9zaWcpLCBzdGF0ID0gJ2lkZW50aXR5Jywgc2hhcGUgPSAyMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIndoaXRlIiwiYmxhY2siLCJncmV5IiksIG5hbWUgPSAiRGlzc2ltaWxhcml0eSB0cmVuZCIsIGd1aWRlPSJub25lIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9zaXplX2Jpbm5lZChyYW5nZSA9IGMoMSw4KSwgbmFtZSA9ICJTdXJ2ZXkgcGVyaW9kIGxlbmd0aFxuKHllYXJzKSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMC4wMDUsIDAuMDA3NSwgYnkgPSAwLjAwMjUpLCBsYWJlbHMgPSBjKCItMC4wMDUiLCIiLCIwIiwgIiIsICIwLjAwNSIsICAiIikpICsKICB4bGFiKCJTdXJ2ZXkgdW5pdCIpICsKICB5bGFiKCLOsi1kaXZlcnNpdHkgdHJlbmQiKSArICN0b3RhbCBCQyBkaXNzaW1pbGFyaXR5IHRyZW5kCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMjUsMC43KSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIpCgojIiM3M0JBNEQiLCIjRTA5NjJDIiwiI2NiYmZkZSIKCkJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2NvbG9yYnl0cmVuZCA8LSBnZ3Bsb3QoKSArCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGZpbGwgPSAiZ3JleSIsIHdpZHRoID0gMCkgKyAjYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgZ2VvbV9wb2ludChkYXRhID0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGFlcyh4ID0gcmVvcmRlcihTdXJ2ZXlfTmFtZV9TZWFzb24sIHllYXJfYWRqKSAsIHkgPSB5ZWFyX2FkaiwgbGFiZWwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpemUgPSB5ZWFyc19zYW1wbGVkLCBjb2xvciA9IERpcmVjdGlvbmFsX0NoYW5nZV9zaWcpLCBzdGF0ID0gJ2lkZW50aXR5JykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjNzNCQTREIiwiI0UwOTYyQyIsIiNjYmJmZGUiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIiwgZ3VpZGU9Im5vbmUiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGhcbih5ZWFycykiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjdG90YWwgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjMsMC44KSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKQoKZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90X2NvbG9yYnl0cmVuZCA8LSBCQ190b3RhbF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZF9jb2xvcmJ5dHJlbmQgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSAidHJhbnNwYXJlbnQiKSwgCiAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NikpLCBzaXplID0gIm5vbmUiKQpgYGAKCmBgYAoKTWVyZ2UgQkMgdmVyc3VzIFllYXIgcGxvdCB3aXRoIEdBTVMgYW5kIFJlZ2lvbiB2cy4gY29lZmZpY2llbnQgcGxvdCBmb3IgTE1zCgpgYGB7cn0KCkJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZCA8LSBnZ2RyYXcoeGxpbSA9IGMoMCwgNDAuNSksIHlsaW0gPSBjKDAsIDIxKSkgKwogICAgZHJhd19wbG90KHBvaW50c193YXZ5bGluZXNfYnJheV90b3RhbF95ZWFyX3JlZHVjZWRfZ2FtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAxLCB5ID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjApICsKICAgIGRyYXdfcGxvdChCQ190b3RhbF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZCArCiAgICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpLCAjY2hhbmdlIGxlZ2VuZCB0ZXh0IGZvbnQgc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDIwLCB5ID0gMSwgd2lkdGggPTE5LCBoZWlnaHQgPSAyMCkgKwogICAgZHJhd19wbG90KGdldF9sZWdlbmQoZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90ICsgCiAgICAgIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAnY20nKSwgI2NoYW5nZSBsZWdlbmQga2V5IHNpemUKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNSksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTMpKSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMjcsIHkgPSAxMCwgd2lkdGggPSAzLCBoZWlnaHQgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMiwgeSA9IDIwLjcpLCBsYWJlbCA9ICgiYS4iKSwgc2l6ZSA9OCwgZm9udGZhY2UgPSAiYm9sZCIpICsKICBnZW9tX3RleHQoYWVzKHggPTIwLCB5ID0gMjAuNyksIGxhYmVsID0gKCJiLiIpLCBzaXplID04LCBmb250ZmFjZSA9ICJib2xkIikKCgpnZ3NhdmUoQkNfdG90YWxfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9ICJCQ190b3RhbF9HQU1fTE1FUl9tZXJnZV9sZWdlbmQucG5nIiwgaGVpZ2h0ID0gOCwgd2lkdGggPSAxNCwgdW5pdHMgPSAiaW4iKQoKI0FMVCBHUkVZIFNDQUxFCkJDX3RvdGFsX0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9ncmV5c2NhbGUgPC0gZ2dkcmF3KHhsaW0gPSBjKDAsIDQwLjUpLCB5bGltID0gYygwLCAyMSkpICsKICAgIGRyYXdfcGxvdChwb2ludHNfd2F2eWxpbmVzX2JyYXlfdG90YWxfeWVhcl9yZWR1Y2VkX2dhbV9ncmV5c2NhbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDEsIHkgPSAxLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAyMCkgKwogICAgZHJhd19wbG90KEJDX3RvdGFsX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2dyZXlzY2FsZSArCiAgICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpLCAjY2hhbmdlIGxlZ2VuZCB0ZXh0IGZvbnQgc2l6ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDIwLCB5ID0gMSwgd2lkdGggPSAxOSwgaGVpZ2h0ID0gMjApICsKICAgIGRyYXdfcGxvdChnZXRfbGVnZW5kKGRpcmVjdGlvbmFsX2NoYW5nZV9sZWdlbmRfcGxvdCArIAogICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLCAjY2hhbmdlIGxlZ2VuZCB0aXRsZSBmb250IHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEzKSkpLCAjY2hhbmdlIGxlZ2VuZCB0ZXh0IGZvbnQgc2l6ZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMjcsIHkgPSAxMCwgd2lkdGggPSAzLCBoZWlnaHQgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMiwgeSA9IDIwLjcpLCBsYWJlbCA9ICgiYS4iKSwgc2l6ZSA9OCwgZm9udGZhY2UgPSAiYm9sZCIpICsKICBnZW9tX3RleHQoYWVzKHggPTIwLCB5ID0gMjAuNyksIGxhYmVsID0gKCJiLiIpLCBzaXplID04LCBmb250ZmFjZSA9ICJib2xkIikKCmdnc2F2ZShCQ190b3RhbF9HQU1fTE1FUl9tZXJnZV9sZWdlbmRfZ3JleXNjYWxlLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9ICJCQ190b3RhbF9HQU1fTE1FUl9tZXJnZV9sZWdlbmRfZ3JleXNjYWxlLnBuZyIsIGhlaWdodCA9IDgsIHdpZHRoID0gMTQsIHVuaXRzID0gImluIikKYGBgCgo=